James
James

Reputation: 1780

How is task scheduling implemented?

I've done a chunk of work to retrieve some data from a web service but now have the problem of scheduling requests to it and I'm not really sure where to begin.

I listen to a jms queue for events and upon receipt of an event I need to make a request to the web service after a duration. The duration varies depending on the event attributes. If the web service returns false I need to continue to schedule requests until it returns true.

I was thinking of creating a lookup request on a queue upon receipt of either an event or a false response, but this doesn't seem ideal - I'd be consuming messages constantly, checking the time to see if a request should be made yet and putting it back on the queue if not.

If anyone's got advice on how to implement such a problem I'd really appreciate it.

Upvotes: 3

Views: 11325

Answers (4)

James
James

Reputation: 1780

I've decided to go with Spring Task Scheduling which has been introduced in version 3. It offers pooling, scheduling based on both instants in time and intervals, and if more customisation is required it has a cron option. I didn't delve into the depths of what can be achieved with Quartz but it also offers integration with that.

Upvotes: 0

Aleksey
Aleksey

Reputation: 1349

I agree with using 3-d party library. I use quartz framework for that. http://www.quartz-scheduler.org/

Upvotes: 4

Erick Robertson
Erick Robertson

Reputation: 33058

First, make sure that you keep the events in the queue in the order in which they need to be executed. This will ensure that you only need to look at the head of the queue to see when the next event should be scheduled. You can use a PriorityQueue for this.

Your thread for processing events will poll items off this queue and process them. Have it peek at the head item and see when the next event needs to be run. Pick an object to use as a locking object and have the main thread call Object.wait(long) on that object, passing the method the number of milliseconds until the next event needs to be run.

If a new thread comes in, add it to the queue in the appropriate place. If the item is at the head of the queue, this means that the thread needs to wake up sooner. Call Object.notifyAll() on the lock object to wake up the processing thread. It will see that there is nothing to process and go back to sleep for the appropriate amount of time.

public class ProcessingQueue extends Thread {

  private PriorityQueue<Task> tasks;  

  private volatile boolean isRunning = true;

  public void addTask(Task t) {
    synchronized (this.tasks) {
      this.tasks.offer(t);
      // this call requires synchronization to this.tasks
      this.tasks.notifyAll();
    }
  }

  public void shutdown() {
    this.isRunning = false;
    synchronized (this.tasks) {
      this.notifyAll();
    }
  }

  public void run() {
    while (this.isRunning) {
      synchronized (this.tasks) {
        Task t = this.tasks.peek();
        // by default, if there are no tasks, this will wake every 60 seconds
        long millisToSleep = 60000;
        // getExecuteMillis() should return the time, in milliseconds, for execution
        if (t != null) millisToSleep = t.getExecuteMillis() - System.currentTimeMillis();
        if (millisToSleep > 0) {
          try {
            // this line requires synchronization to this.tasks
            // and the lock is removed while it waits
            this.tasks.wait(millisToSleep);
          } catch (InterruptedException e) {
          }
        }
        t = this.tasks.poll();
        if (t != null) {
          t.execute();
        }
      }
    }
  }
}

Upvotes: 6

Peter Knego
Peter Knego

Reputation: 80330

Use an existing OSS scheduler: http://java-source.net/open-source/job-scheduler

You can always roll you own, but I'd not recommend it.

One important feature of a scheduler should be that it survives restart/crash.

Upvotes: 2

Related Questions