code: private void runJob(Job jobToRun) {
  		long startExecutionTime = timeProvider.currentTime();
  		long timeBeforeNextExecution = jobToRun.nextExecutionTimeInMillis() - startExecutionTime;
  		if(timeBeforeNextExecution < 0) {
  			logger.debug("Job '{}' execution is {}ms late", jobToRun.name(), -timeBeforeNextExecution);
  		}
  		jobToRun.status(JobStatus.RUNNING);
  		jobToRun.lastExecutionStartedTimeInMillis(startExecutionTime);
  		jobToRun.threadRunningJob(Thread.currentThread());
  
  		try {
  			jobToRun.runnable().run();
  		} catch(Throwable t) {
  			logger.error("Error during job '{}' execution", jobToRun.name(), t);
  		}
  		jobToRun.executionsCount(jobToRun.executionsCount() + 1);
  		jobToRun.lastExecutionEndedTimeInMillis(timeProvider.currentTime());
  		jobToRun.threadRunningJob(null);
  
  		if(logger.isDebugEnabled()) {
  			logger.debug(
  				"Job '{}' executed in {}ms", jobToRun.name(),
  				timeProvider.currentTime() - startExecutionTime
  			);
  		}
  
  		if(shuttingDown) {
  			return;
  		}
  		synchronized (this) {
  			scheduleNextExecution(jobToRun);
  		}
  	}
docs: The wrapper around a job that will be executed in the thread pool.
  It is especially in charge of logging, changing the job status
  and checking for the next job to be executed.
  @param jobToRun the job to execute