Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Executors: how can I set task priority?

Is there a possibility to set priority to tasks which are executed by Executors? I've found some statements in JCIP about it's possible but I cannot find any example and I cannot find anything related in docs.

From JCIP:

An execution policy specifies the "what, where, when, and how" of task execution, including:

  • ...
  • In what order should tasks be executed (FIFO, LIFO, priority order)?
  • ...

UPD: I realized that I asked not exactly what I wanted to ask. What I really wanted is:

How to use/emulate setting threads priority (i.e. what was thread.setPriority()) with executors framework?

like image 854
Roman Avatar asked Jul 07 '10 20:07

Roman


People also ask

How do you set a priority in Java?

It can be changed using the method setPriority() of class Thread. There are three static variables for thread priority in Java i.e. MIN_PRIORITY, MAX_PRIORITY and NORM_PRIORITY. The values of these variables are 1, 10 and 5 respectively.

How do I set high priority in Java?

If java process has normal priority it may not get system resources as much as it need. I can set this process priority to high from windows task manager by going to a process right click it and set priority as high.


2 Answers

Currently the only concrete implementations of the Executor interface are the ThreadPoolExecutor and the ScheduledThreadpoolExecutor

Instead of using the utility / factory class Executors, you should create an instance using a constructor.

You can pass a BlockingQueue to the constructors of the ThreadPoolExecutor.

One of the implementations of the BlockingQueue, the PriorityBlockingQueue lets you pass a Comparator to a constructor, that way enabling you to decide the order of execution.

like image 97
Davy Meers Avatar answered Sep 22 '22 11:09

Davy Meers


The idea here is to use a PriorityBlockingQueue in the executor. For this:

  • Create a comparator that would compare our futures.
  • Create a proxy for the Future to hold a priority.
  • Override 'newTaskFor' in order to wrap every future in our proxy.

First you need to hold priority on your future:

    class PriorityFuture<T> implements RunnableFuture<T> {      private RunnableFuture<T> src;     private int priority;      public PriorityFuture(RunnableFuture<T> other, int priority) {         this.src = other;         this.priority = priority;     }      public int getPriority() {         return priority;     }      public boolean cancel(boolean mayInterruptIfRunning) {         return src.cancel(mayInterruptIfRunning);     }      public boolean isCancelled() {         return src.isCancelled();     }      public boolean isDone() {         return src.isDone();     }      public T get() throws InterruptedException, ExecutionException {         return src.get();     }      public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {         return src.get();     }      public void run() {         src.run();     } } 

Next you need to define comparator that would correctly sort the priority futures:

class PriorityFutureComparator implements Comparator<Runnable> {     public int compare(Runnable o1, Runnable o2) {         if (o1 == null && o2 == null)             return 0;         else if (o1 == null)             return -1;         else if (o2 == null)             return 1;         else {             int p1 = ((PriorityFuture<?>) o1).getPriority();             int p2 = ((PriorityFuture<?>) o2).getPriority();              return p1 > p2 ? 1 : (p1 == p2 ? 0 : -1);         }     } } 

Next let's assume we have a lengthy job like this:

class LenthyJob implements Callable<Long> {     private int priority;      public LenthyJob(int priority) {         this.priority = priority;     }      public Long call() throws Exception {         System.out.println("Executing: " + priority);         long num = 1000000;         for (int i = 0; i < 1000000; i++) {             num *= Math.random() * 1000;             num /= Math.random() * 1000;             if (num == 0)                 num = 1000000;         }         return num;     }      public int getPriority() {         return priority;     } } 

Then in order to execute these jobs in priority the code will look like:

public class TestPQ {      public static void main(String[] args) throws InterruptedException, ExecutionException {         int nThreads = 2;         int qInitialSize = 10;          ExecutorService exec = new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,                 new PriorityBlockingQueue<Runnable>(qInitialSize, new PriorityFutureComparator())) {              protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {                 RunnableFuture<T> newTaskFor = super.newTaskFor(callable);                 return new PriorityFuture<T>(newTaskFor, ((LenthyJob) callable).getPriority());             }         };          for (int i = 0; i < 20; i++) {             int priority = (int) (Math.random() * 100);             System.out.println("Scheduling: " + priority);             LenthyJob job = new LenthyJob(priority);             exec.submit(job);         }     } } 

This is a lot of code but that's nearly the only way this can be accomplished.

On my machine the output is like the following:

Scheduling: 39 Scheduling: 90 Scheduling: 88 Executing: 39 Scheduling: 75 Executing: 90 Scheduling: 15 Scheduling: 2 Scheduling: 5 Scheduling: 24 Scheduling: 82 Scheduling: 81 Scheduling: 3 Scheduling: 23 Scheduling: 7 Scheduling: 40 Scheduling: 77 Scheduling: 49 Scheduling: 34 Scheduling: 22 Scheduling: 97 Scheduling: 33 Executing: 2 Executing: 3 Executing: 5 Executing: 7 Executing: 15 Executing: 22 Executing: 23 Executing: 24 Executing: 33 Executing: 34 Executing: 40 Executing: 49 Executing: 75 Executing: 77 Executing: 81 Executing: 82 Executing: 88 Executing: 97 
like image 21
Stanislav Vitvitskyy Avatar answered Sep 20 '22 11:09

Stanislav Vitvitskyy