美文网首页
09 线程池番外:CompletionService

09 线程池番外:CompletionService

作者: 攻城狮哦哦也 | 来源:发表于2019-08-26 14:03 被阅读0次

1 CompletionService作用

使用Future和Callable可以获取线程执行结果,但获取方式确实阻塞的,根据添加到线程池中的线程顺序,依次获取,获取不到就阻塞。
为了解决这种情况,可以采用轮询的做法。
CompletionService可以异步非阻塞获取并行任务执行结果

2 案例


public class CompletionCase {
    private final int POOL_SIZE = Runtime.getRuntime().availableProcessors();
    private final int TOTAL_TASK = Runtime.getRuntime().availableProcessors();

    // 方法一,自己写集合来实现获取线程池中任务的返回结果
    public void testByQueue() throws Exception {
        long start = System.currentTimeMillis();
        //统计所有任务休眠的总时长
        AtomicInteger count = new AtomicInteger(0);
        // 创建线程池
        ExecutorService pool = Executors.newFixedThreadPool(POOL_SIZE);
        //容器存放提交给线程池的任务,list,map,
        BlockingQueue<Future<Integer>> queue = 
                new LinkedBlockingQueue<Future<Integer>>();

        // 向里面扔任务
        for (int i = 0; i < TOTAL_TASK; i++) {
            Future<Integer> future = pool.submit(new WorkTask("ExecTask" + i));
            queue.add(future);//i=0 先进队列,i=1的任务跟着进
        }

        // 检查线程池任务执行结果
        for (int i = 0; i < TOTAL_TASK; i++) {
            int sleptTime = queue.take().get();///i=0先取到,i=1的后取到
            System.out.println(" slept "+sleptTime+" ms ...");          
            count.addAndGet(sleptTime);
        }

        // 关闭线程池
        pool.shutdown();
        System.out.println("-------------tasks sleep time "+count.get()
                +"ms,and spend time "
                +(System.currentTimeMillis()-start)+" ms");
    }

    // 方法二,通过CompletionService来实现获取线程池中任务的返回结果
    public void testByCompletion() throws Exception {
        long start = System.currentTimeMillis();
        AtomicInteger count = new AtomicInteger(0);
        // 创建线程池
        ExecutorService pool = Executors.newFixedThreadPool(POOL_SIZE);
        CompletionService<Integer> cService = new ExecutorCompletionService<>(pool);
        
        // 向里面扔任务
        for (int i = 0; i < TOTAL_TASK; i++) {
            cService.submit(new WorkTask("ExecTask" + i));
        }
        
        // 检查线程池任务执行结果
        for (int i = 0; i < TOTAL_TASK; i++) {
            int sleptTime = cService.take().get();
            System.out.println(" slept "+sleptTime+" ms ...");          
            count.addAndGet(sleptTime);
        }        

        // 关闭线程池
        pool.shutdown();
        System.out.println("-------------tasks sleep time "+count.get()
            +"ms,and spend time "
            +(System.currentTimeMillis()-start)+" ms");
    }

    public static void main(String[] args) throws Exception {
        CompletionCase t = new CompletionCase();
        t.testByQueue();
        t.testByCompletion();
    }
}

运行结果:

 slept 6 ms ...
 slept 825 ms ...
 slept 792 ms ...
 slept 264 ms ...
 slept 896 ms ...
 slept 783 ms ...
 slept 549 ms ...
 slept 117 ms ...
 slept 287 ms ...
 slept 642 ms ...
 slept 769 ms ...
 slept 425 ms ...
-------------tasks sleep time 6355ms,and spend time 899 ms
 slept 10 ms ...
 slept 71 ms ...
 slept 180 ms ...
 slept 186 ms ...
 slept 205 ms ...
 slept 368 ms ...
 slept 373 ms ...
 slept 429 ms ...
 slept 497 ms ...
 slept 548 ms ...
 slept 693 ms ...
 slept 775 ms ...
-------------tasks sleep time 4335ms,and spend time 776 ms

可以看出,使用了CompletionService,线程池返回的结果,是先返回则先获取,节省了资源,提高了效率。
而只使用线程池和Future的线程池执行结果则是按顺序阻塞获取的

相关文章

  • 09 线程池番外:CompletionService

    1 CompletionService作用 使用Future和Callable可以获取线程执行结果,但获取方式确实...

  • 12.线程池-5

    CompletionService介绍 通过上面的截图,我们大概可以猜到CompletionService跟线程池...

  • 四、线程池及异步编程

    线程池ThreadPool 任务队列+多线程生产者-消费者模式 2、CompletionService,线程池+结...

  • Java多线程6 CompletionService

    Java多线程目录 CompletionService 1 CompletionService介绍 Complet...

  • java线程池

    title: java线程池date: 2017-02-03 09:27:23tags: concurrencyc...

  • 并发编程实战二之线程池和CompletionService

    线程池 线程饥饿死锁 任务依赖于其他任务,线程池不够大单线程,一个任务将另一个任务提交到同一个Executor。 ...

  • ThreadPoolExecutor

    参考文章:Java并发学习之线程池ThreadPoolExecutor的小结并发番@ThreadPoolExecu...

  • Java多线程-CompletionService

    起 原文地址 http://blog.csdn.net/qq_25806863/article/details/7...

  • java线程池

    线程VS线程池 普通线程使用 创建线程池 执行任务 执行完毕,释放线程对象 线程池 创建线程池 拿线程池线程去执行...

  • java----线程池

    什么是线程池 为什么要使用线程池 线程池的处理逻辑 如何使用线程池 如何合理配置线程池的大小 结语 什么是线程池 ...

网友评论

      本文标题:09 线程池番外:CompletionService

      本文链接:https://www.haomeiwen.com/subject/amhxectx.html