Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java interject Runnable objects into ExecutorService

I have a single thread pool ExecutorService object. At some time in the future tasks are added to be done using the submit() method. My understanding is that submit will submit add the submitted Runnable to the end of the list of tasks to be done. However I have a situation where based on a boolean I may want to submit the runnable to the front of the tasks to be executed. I don't want this to affect the current task, just that the next task done will be the one I just gave it. An example method is reproduced below. How do I do this?

Thanks

private ExecutorService singleLoadPool = Executors.newSingleThreadExecutor();
public void submitTask(Runnable run, boolean doNow) {
    if (doNow)
        singleLoadPool.submitFront(run);  // This is the method I'm looking for
    else
        singleLoadPool.submit(run);
}
like image 566
Jon Avatar asked Aug 01 '12 19:08

Jon


2 Answers

My preference would be use a LinkedBlockingDeque. It directly supports positional inserts/removes - putFirst(e)/takeFirst() and putLast(e)/takeLast() - which is your primary requirement- you dont have to implement a Comparator for your elements. Also this is bounded - which means that it provides safety against OutOfMemoryError.

edit In response to latest question :

First , have the ExecutorService like

ExecutorService executorService = new ThreadPoolExecutor(1, 1, 1, TimeUnit.SECONDS, workQueue);

Second , the important question is : what is the workQueue ?

The workQueue is a thin wrapper over any BlockingQueue implementation , which delegates all its methods to a LinkedBlockingDeque instance that it contains, except for the offer() method , which is called on it by the ThreadPoolExecutor and which needs to be overriden, like this :

       public boolean offer(E e) {
       if(doNow)
         return linkedBlockingDequeInstance.offerFirst(e);
      else 
         return linkedBlockingDequeInstance.offerLast(e);
   }

Ofcourse when you override any method - you need to careful to preserve thread safety and its general contract.Definitely this requires careful thought and rigorous testing.

like image 153
Bhaskar Avatar answered Oct 29 '22 17:10

Bhaskar


I think your best approach for this would be to instantiate a ThreadPoolExecutor with a PriorityBlockingQueue. Specifically, use a PriorityBlockingQueue constructor that takes in a Comparator. Your Comparator will be what you use to implement your 'priority'.

PriorityBlockingQueue<Runnable> workQueue = new PriorityBlockingQueue<Runnable>(20, yourPriorityComparator);
ExecutorService executorService = new ThreadPoolExecutor(1, 1, 1, TimeUnit.SECONDS, workQueue);
like image 21
nicholas.hauschild Avatar answered Oct 29 '22 17:10

nicholas.hauschild