@ SneakyThrows private void launcher ( ) { while ( ! shuttingDown ) { Long timeBeforeNextExecution = null ; synchronized ( this ) { if ( nextExecutionsOrder . size ( ) > 0 ) { timeBeforeNextExecution = nextExecutionsOrder . get ( 0 ) . nextExecutionTimeInMillis ( ) - timeProvider . currentTime ( ) ; } } if ( timeBeforeNextExecution == null || timeBeforeNextExecution > 0L ) { synchronized ( launcherNotifier ) { if ( shuttingDown ) { return ; } // If someone has notified the launcher // then the launcher must check again the next job to execute. // We must be sure not to miss any changes that would have // happened after the timeBeforeNextExecution calculation. if ( launcherNotifier . get ( ) ) { if ( timeBeforeNextExecution == null ) { launcherNotifier . wait ( ) ; } else { launcherNotifier . wait ( timeBeforeNextExecution ) ; } } launcherNotifier . set ( true ) ; } } else { synchronized ( this ) { if ( shuttingDown ) { return ; } if ( nextExecutionsOrder . size ( ) > 0 ) { Job jobToRun = nextExecutionsOrder . remove ( 0 ) ; jobToRun . status ( JobStatus . READY ) ; jobToRun . runningJob ( ( ) -> runJob ( jobToRun ) ) ; if ( threadPoolExecutor . getActiveCount ( ) == threadPoolExecutor . getMaximumPoolSize ( ) ) { logger . warn ( "Job thread pool is full, either tasks take too much time to execute" + " or either the thread pool is too small" ) ; } threadPoolExecutor . execute ( jobToRun . runningJob ( ) ) ; } } } } }
The daemon that will be in charge of placing the jobs in the thread pool when they are ready to be executed .