Java threads of CompletionService

background

When we need to deal with a number of tasks, and need when the task is completed, the results can be obtained when the task, we how to do it.

  • The first scenario is: Save the Future associated with each task, and then the main thread through each Future were get, because the will get blocked, we can only timeot set to 0, but this will be relatively large performance overhead.
  • The second option: use a blocking queue, each task as a producer thread after processing is complete, the results put into blocking queue. As consumers like the main thread from blocking queue take, if not content to clog.
  • The third scheme: directly CompletionService, a specific category is ExecutorCompletionService.

ExecutorCompletionService

The sample code

public class CompletionServiceDemo implements Callable<Integer> {
    Random r = new Random();
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        new CompletionServiceDemo().process();
    }

    public void process() throws InterruptedException, ExecutionException {
        Executor executor = Executors.newFixedThreadPool(2);
        CompletionService<Integer> completionService = new ExecutorCompletionService<>(executor);
        int taskCount = 5;
        for (int i = 0; i < taskCount; i++) {
            completionService.submit(this);
        }
        int sum = 0;
        for (int i = 0; i < taskCount; i++) {
            Integer res = completionService.take().get();
            sum += res;
        }
        System.out.println(sum);

    }
    @Override
    public Integer call() throws Exception {
        int i = r.nextInt(500);
        Thread.sleep(i);
        return i;
    }
}

 

The principle

ExecutorCompletionService encapsulates Executor and BlockingQueue ,. Callable first submitted to Executor task, the task is then packaged into QueueingFuture, which is a subclass FutureTask, then override done method, i.e., executing the thread into the Future object in BlockingQueue. done method is a callback method, when FutureTask implementation of the latter would result set objects, then it will be done callback method. take and poll method delegates to the BlockingQueue, it will be blocked while the results are not available. Such tasks which first executed, the results of which corresponding to the task can first obtain the

Part of the source code

public class ExecutorCompletionService<V> implements CompletionService<V> {
    private final Executor executor;
    private final BlockingQueue<Future<V>> completionQueue;
    ...
    private class QueueingFuture extends FutureTask<Void> {
        QueueingFuture(RunnableFuture<V> task) {
            super(task, null);
            this.task = task;
        }
        protected void done() { completionQueue.add(task); }
        private final Future<V> task;
    }
    ...
    public Future<V> submit(Callable<V> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<V> f = newTaskFor(task);
        executor.execute(new QueueingFuture(f));
        return f;
    }
    ....
    public Future<V> take() throws InterruptedException {
        return completionQueue.take();
    }
    ...
}

 

Guess you like

Origin www.cnblogs.com/hello---word/p/11105297.html