CompletionService小记

CompletionService小记java

在使用ExecutorService时,经过sumit执行一个Callable的时候,会当即返回一个异步任务结果,而后经过get获取异步任务结果的时候会阻塞,以下面这种状况,代码以下,异步

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * Created by xinxingegeya on 16/3/22.
 */
public class ExecutorServiceTest {

    public static void main(String args[])
            throws ExecutionException, InterruptedException {

        ExecutorService executor = Executors.newCachedThreadPool();

        List<Future<Integer>> futureList = new ArrayList<>();
        for (int i = 5; i > 0; i--) {
            final int taskID = i;
            //CompletionService.submit()
            Future<Integer> res = executor.submit(new Callable<Integer>() {
                public Integer call() throws Exception {
                    Thread.sleep(taskID * 1000);
                    return taskID;
                }
            });
            futureList.add(res);
        }

        for (Future<Integer> future : futureList) {
            int result = future.get();
            System.out.println(result);
        }

        executor.shutdown();

        while (executor.isTerminated()) {
            executor.awaitTermination(1000, TimeUnit.MILLISECONDS);
        }
    }
}

经过代码能够看到,在遍历任务结果集的时候,获取第一个任务结果,而后get会阻塞,会阻塞大概五秒的时间,而对于后面的任务,可能已经执行完成了,但就是阻塞在了第一Future上,这是不合理的,那么如何改进,在这里应该要使用CompletionService,以下代码,spa

import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * Created by xinxingegeya on 16/3/22.
 */
public class ExecutorCompletionServiceTest {

    public static void main(String args[]) throws InterruptedException {

        ExecutorService executor = Executors.newCachedThreadPool();

        CompletionService<Integer> cs = new ExecutorCompletionService<>(
            executor);
        for (int i = 5; i > 0; i--) {
            final int taskID = i;
            //CompletionService.submit()
            cs.submit(new Callable<Integer>() {
                public Integer call() throws Exception {
                    Thread.sleep(taskID * 1000);
                    return taskID;
                }
            });
        }
        // 可能作一些事情
        for (int i = 1; i < 5; i++) {
            try {
                int result = cs.take().get();//CompletionService.take()返回Future
                System.out.println(result);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }

        executor.shutdown();

        while (executor.isTerminated()) {
            executor.awaitTermination(1000, TimeUnit.MILLISECONDS);
        }

        System.out.println("done");
    }
}

使用CompletionService的好处就是优先获取已经执行完成的任务结果,而不会一味的等待尚未执行完成的任务。code

CompletionService的实现机制就是利用BlockingQueue,若是任务已经执行完成,会把Future放进阻塞队列里面,若是阻塞队列中有已经完成的任务,那么就取出来(take)获取异步任务的结果。队列

==============END==============get

相关文章
相关标签/搜索