How to get ThreadPoolExecutor to execute immediately in Java

ABC :

I have a ThreadPoolExecutor and a Runnable called this.runnable. I run it like this:

ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
executor.execute(this.runnable);

Usually, this.runnable will be called almost immediately (100-200us after). But sometimes if a CPU is busy it can take a while to run.

Is there a way I can "force" this to execute immediately, or suggest to the JVM/ThreadPoolExecutor to prioritse this thread's execution? I need to keep it as a separate thread but at the same time, I need it to start running with urgency.

Nathan Hughes :

You could use a PriorityBlockingQueue to queue the tasks. That way a high priority task can be given the highest spot in the queue so it runs as soon as a worker is freed up. But I don't like this option because it adds complication and overhead, and low-priority tasks may get starved.

Dinking around with thread priorities usually doesn't work out well. Different platforms implement different priority levels so code relying on priorities may have different behavior on different platforms. Also having different priority threads makes it easy to cause a priority inversion bug. Here is what the book Java Concurrency in Practice (10.3.1) has to say about priorities:

It is generally wise to resist the temptation to tweak thread priorities. As soon as you start modifying priorities, the behavior of your application becomes platform-specific and you introduce the risk of starvation. You can often spot a program that is trying to recover from priority tweaking or other responsiveness problems by the presence of Thread.sleep or Thread.yield calls in odd places, in an attempt to give more time to lower-priority threads.

As others have said before, you can't prevent other processes from using the CPU (you would have to move your application to a platform where it isn't competing with other processes for CPU), and you can't force the OS to schedule and run a particular thread.

You don't have to limit yourself to just one threadpool, there are sometimes good reasons to have multiple pools. JCIP (8.1) advises:

Thread pools work best when tasks are homogeneous and independent. Mixing long-running and short-running tasks risks "clogging" the pool unless it is very large; submitting tasks that depend on other tasks risks deadlock unless the pool is unbounded.

If you have a short task that needs doing right away, and it tends to get stuck getting queued up behind multiple bigger tasks, then you need another dedicated threadpool for high-priority tasks.

What I would do:

  • First, make sure the threadpool is initialized only once, on startup, and adjust the size of the threadpool to have more than one thread. With only one thread your task may just be blocked behind another one.

  • If CPU is an issue, consider changing where your application is deployed so it doesn't have to share CPU with other processes, or otherwise fix the hosting so there's more CPU to go around.

  • If the pool continues to be a bottleneck then make a separate thread pool to use as a fast lane for high priority tasks.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=306992&siteId=1