I have an Executors.newFixedThreadPool(1) that I send several different tasks to (all im开发者_Go百科plementing Runnable), and they get queued up and run sequentially correct? What is the best way to only allow one of each task to be either running or queued up at one time? I want to ignore all tasks sent to the ExecutorService that are already in the queue.
I have an Executors.newFixedThreadPool(1) that I send several different tasks to (all implementing Runnable), and they get queued up and run sequentially correct?
Yes, by default the underlying thread pool executor is created with a LinkedBlockingQueue. Since you have only one worker thread and the queue is used in a FIFO manner, tasks will be executed in order.
What is the best way to only allow one of each task to be either running or queued up at one time? I want to ignore all tasks sent to the ExecutorService that are already in the queue.
The easiest way I can think is to create your own ExecutorService which extends a ThreadPoolExecutor. Then override the execute() method such that you call BlockingQueue#contains(Object) prior to delegating to the super classes execute.
public class LimitedExecutorService extends ThreadPoolExecutor {
public LimitedExecutorService(final int nThreads) {
super(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
}
@Override
public void execute(Runnable command) {
if (!this.getQueue().contains(command)) {
super.execute(command);
} else {
//reject
}
}
}
Note: Many people will argue that you should not extend a ThreadPoolExecutor, but instead say you implement ExecutorService and have your class contain a ThreadPoolExecutor which you delegate to (aka composition).
The thread pool does not guarantee task ordering.
As for the second part you can set the rejected execution handler, using ThreadPoolExecutor.DiscardPolicy
using ThreadPoolExecutor
精彩评论