Conditional delayed processing

101 views Asked by At

I have created a new thread pool and a new associated listener under glassfish. The thread pool has a maximum capacity of 100 threads. I have a scheduled job running every night which should trigger a HTTP GET request from remote client. Note that the scheduled job is NOT a HTTP client. It however triggers remote HTTP clients to make a HTTP GET requests. The number of requests can exeed more than 100. The scheduled job should run in a un-interrupted way even if the number of request exceed 100. Below is the psuedo code

class ScheduledJob{

    public executeJob(){
    {
        for(i=0; i<=numberOfTasks; i++)
        {
            connectToTheClientsAndAskThemToFireHTTPGetRequests();
        }
    }

}

The way I would like to design the solution is to make the executeJob method execute in a non-blocking way.That would mean 100 requests are fired initially and the rest of the requests are cached. On receipt of 200 OK, I would then throttle the remaining requests. Note that the HTTP request could take a few seconds as the response HTTP GET is a 20MB binary file. The question here is is there any out of the box solution (data-structure) to perform my caching and triggering business logic OR can anyone suggest a better solution.

1

There are 1 answers

0
Zim-Zam O'Pootertoot On

One option would be to create a Runnable that takes a concurrent queue of GetTasks (or whatever you want to name the wrapper for the HTTP GET request data). executeJob() fills the queue with all of the GetTasks, constructs a thread pool of 100 threads, and submits 100 Runnables that share the same concurrent queue. The Runnables will poll the queue until it is empty, at which point they terminate.

public class GetTask {}

public class GetTaskExecutor implements Runnable {
   private final ConcurrentLinkedQueue<GetTask> queue;

   public GetTaskExecutor(ConcurrentLinkedQueue<GetTask> queue) {
     this.queue = queue;
   }

   public void run() {
     GetTask task = null;
     while((task = queue.poll()) != null) {
       // do work
     }
   }
}

class ScheduledJob{
    public boolean executeJob(){
        ExecutorService service = Executors.newFixedThreadPool(100);
        ConcurrentLinkedQueue<GetTask> queue = new ConcurrentLinkedQueue<>();
        for(i=0; i<=numberOfTasks; i++) {
            queue.offer(new GetTask());
        }
        for(int i = 0; i < 100; i++) {
            service.execute(new GetTaskExecutor(queue));
        }
        return service.awaitTermination(4, TimeUnit.HOURS);
    }
}

An alternative is to create one GetTaskExecutor per GetTask and submit them all to the ExecutorService - you're using a fixed thread pool so at most 100 tasks will execute at a time.

public class GetTaskExecutor implements Runnable {
   private final GetTask task;

   public GetTaskExecutor(GetTask task) {
     this.task = task;
   }

   public void run() {
     // do work on single task
   }
}

class ScheduledJob{
    public boolean executeJob(){
        ExecutorService service = Executors.newFixedThreadPool(100);
        for(i=0; i<=numberOfTasks; i++) {
            service.execute(new GetTaskExecutor(new GetTask());
        }
        return service.awaitTermination(4, TimeUnit.HOURS);
    }
}