0

Is there a way to prioritize tasks for execution in a Java ThreadPoolExecutor? The problem that I am facing is that there are threads that need to be executed in order when based on an identical specified execution identifier.

They are all submitted to the same ThreadPoolExecutor but due to processing delays it is possible that task A2 completes before task A1 (which has the same execution identifier). They should follow the same ordering as when they enter while not blocking other tasks (with different execution identifiers) from executing (e.g. B1, B2, C1, etc.).

Is there a common pattern for handling a problem like that? For example, tasks A1, B1, B2, A2, C1 enter the pool for processing. They should be processed in the following manner:

A1

B1

B2 (if B1 has completed, otherwise wait until B1 completes while A2 or C1 take turn)

A2 (if A1 has completed, otherwise wait until A1 completes while B2, if not started already, or C1 take turn)

C1

heeboir
  • 729
  • 1
  • 9
  • 26

2 Answers2

1

You can create a ThreadPoolExecutor with a PriorityBlockingQueue.

assylias
  • 321,522
  • 82
  • 660
  • 783
  • Thanks for the suggestion. In this case, would the priority be determined upon entering the queue or while in the queue? For example, if B1 is still in processing, then B2 should have a low priority but if B1 has completed, then B2 should have a high priority and be the next in line. – heeboir Jul 02 '14 at 13:48
  • Mmmm - I had not completely read the end of your question. Not sure there is an easy way to achieve that... Wouldn't it be easier to use 3 single threaded executors, one for As, one for Bs and one for Cs? – assylias Jul 02 '14 at 13:52
  • Not your fault, I messed up the formatting so it wasn't very clear before what I meant. On to the problem itself, the A/B/Cs will be in the order of thousands (each represents a user and each attached numeric represents a user action event). I'll have to think about it more.. – heeboir Jul 02 '14 at 13:58
  • @heeboir so As, Bs and Cs can execute in parallel independently, but As need to be processed in order (A1 before A2 before A3), and same for Bs and Cs? – assylias Jul 02 '14 at 14:01
  • Yes, exactly - otherwise I am running into ordering issues with external components.. – heeboir Jul 02 '14 at 14:06
0

Make use of java.util.concurrent package instead of thread pool. It had Future tasks which can help you in ordering and queuing your actionable items.

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html

Update 1:

You can use the following sample. Please correct me if I am wrong, one thing which I see missing in Java FutureTasks is chaining. In .NET you can Chain multiple tasks and define dependencies (e.g. ContinueWith and TaskContinuationOptions, Wait(task) etc..) outside the body of individual task's Call method.

package sample;
import java.util.concurrent.*;

public class FutureTaskTest {

    public static void main(String[] args)
    {

         ExecutorService executor = Executors.newFixedThreadPool(3);

         final FutureTask<String> a1 = new FutureTask<String>(
                    new Callable<String>()
                    {
                        public String call()
                        {
                           System.out.println("a1 finished.");
                           return "Success";

                        }
                    });

         FutureTask<String> a2 = new FutureTask<String>(
                    new Callable<String>()
                    {
                        public String call()
                        {
                           try {
                            a1.get();
                        } catch (InterruptedException | ExecutionException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }//wait for a1 to finish.
                           System.out.println("a2 finished.");
                           return "Success";
                        }
                    });
         final FutureTask<String> b1 = new FutureTask<String>(
                    new Callable<String>()
                    {
                        public String call()
                        {
                            System.out.println("b1 finished.");
                            return "Success";
                        }
                    });
         FutureTask<String> b2 = new FutureTask<String>(
                    new Callable<String>()
                    {
                        public String call()
                        {
                            try {
                                b1.get();
                            } catch (InterruptedException | ExecutionException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }//wait for b1 to finish.
                           System.out.println("b2 finished.");
                            return "Success";
                        }
                    });
         FutureTask<String> c1 = new FutureTask<String>(
                    new Callable<String>()
                    {
                        public String call()
                        {
                            System.out.println("c1 finished.");
                            return "Success";
                        }
                    });


         executor.execute(a1);
         executor.execute(a2);
         executor.execute(b1);
         executor.execute(b2);
         executor.execute(c1);
         }

}

And here is the output.

a1 finished.
b1 finished.
b2 finished.
c1 finished.
a2 finished.

Regards Kajal

Kajal Sinha
  • 1,565
  • 11
  • 20
  • Thanks for the reply. Could you elaborate a bit on how the future tasks could be used in this case? – heeboir Jul 02 '14 at 14:17