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?
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.
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.
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.
The idea here is to use a PriorityBlockingQueue in the executor. For this:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With