### Job scheduling

Our examples so far have demonstrated simple job creation, scheduling, and progress reporting. The job scheduling mechanism is actually more powerful than we've shown so far. You can have more fine-grained control over the way your job is scheduled by using priorities, delays, and custom scheduling conditions.

#### Job priorities

A job priority can be used to establish the importance of a job relative to other jobs in the system. Setting the priority of a job won't affect a job that is already running, but it will affect how a waiting job is scheduled relative to other jobs. The priority of a job can be one of several pre-defined priority constants:

- INTERACTIVE jobs generally have priority over other jobs. They should be short-running or low on processor usage, so that they don't block other INTERACTIVE jobs from running.
- SHORT jobs typically complete within a second, but may take a little longer. They run in the background and have priority over all jobs except INTERACTIVE jobs.
- LONG jobs are for longer running background jobs. They run only after INTERACTIVE and SHORT jobs have been run.
- BUILD jobs are for jobs associated with building tasks. They are a lower priority than LONG. BUILD jobs only run when all LONG jobs are complete.
- DECORATE jobs are the lowest priority in the system. They are used for tasks that provide information that may help supplement the UI, but that the user is not generally waiting for.

The default priority for a job is LONG. The following snippet creates the trivial job we used earlier, but sets the priority to DECORATE to indicate that it is the lowest level priority:

       TrivialJob job = new TrivialJob();
       job.setPriority(Job.DECORATE);
       job.schedule();

#### Scheduling with a delay

Another technique for controlling how a job is scheduled is to use a scheduling delay. A scheduling delay can be specified when the job is scheduled. The job will be delayed for the specified number of milliseconds before it is scheduled.

       TrivialJob job = new TrivialJob();
       job.schedule(1000);  // wait one second before scheduling

#### Rescheduling a job

Scheduling a job that is already waiting or is sleeping has no effect. However, scheduling a job that is already running will cause it to be rescheduled after it is finished. This is a convenient mechanism for repetitive jobs such as background polling loops. If the job is rescheduled multiple times while it is running, it will only be rescheduled once with the most recently supplied delay. The following snippet defines a job that reschedules itself to run 10 seconds after it finishes the current iteration.

       class RepetitiveTrivialJob extends Job {
          public RepetitiveTrivialJob() {
             super("Repetitive Trivial Job");
          }
          public IStatus run(IProgressMonitor monitor) {
             System.out.println("Running the job.");
             // reschedule after 10 seconds
             schedule(10000);
             return Status.OK_STATUS;
          }
       }

#### Custom scheduling conditions

Additional protocol in the Job class allows a job to check for preconditions just before it is scheduled or run. This is best demonstrated by example:

    class JobWithPreconditions extends Job {
    	...
    	public boolean shouldSchedule() {
    		return super.shouldSchedule() && checkJobPreconditions();
    	}
    	public boolean shouldRun() {
    		return super.shouldRun() && checkJobPreconditions();
    	}
    	...
    }

The shouldSchedule method is called just before the job manager places the job in the queue. This allows the job to cancel itself if basic preconditions for scheduling are not met. The job should return `false` it is inappropriate to schedule it. Likewise, the shouldRun method is called just before the job manager runs the job. Any additional conditions that must be met before the job is run must be checked at this time.