• CompletionService之一:获得线程(线程池的)处理结果


    Thread之四:java线程返回结果的方法

    Runnable、Callable、Future和FutureTask之一:获取线程的返回值

    CompletionService之一:获得线程(线程池的)处理结果

    使用线程池的时候,经常会有需要获得线程处理结果的时候。此时我们通常有两种做法:

    1. 使用并发容器将callable.call() 的返回Future存储起来。然后使用一个消费者线程去遍历这个并发容器,调用Future.isDone()去判断各个任务是否处理完毕。然后再处理响应的业务。

    2. 使用jdk 自带线程池结果管理器:ExecutorCompletionService。它将BlockingQueue 和Executor 封装起来。然后使用ExecutorCompletionService.submit()方法提交任务。

    示例1:用BlockingQueue存放结果:

    package com.transsnet.palmpay.cfront.test;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.LinkedBlockingQueue;
    
    public class ExecutorResultManager {
    
        public static void main(String[] args) {
            // 队列
            BlockingQueue<Future<String>> futures = new LinkedBlockingQueue<>();
            
            // 生产者
            new Thread() {
                @Override
                public void run() {
                    ExecutorService pool = Executors.newCachedThreadPool();
                    
                    for (int i=0; i< 10; i++) {
                        int index = i;
                        Future<String> submit = pool.submit(new Callable<String>() {
                            @Override
                            public String call() throws Exception {
                                return "task done" + index;
                            }
                        });
                        try {
                            futures.put(submit);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
            
            
            System.out.println("---------------------");
            System.out.println(futures.size());
            // 消费者
            new Thread() {
                @Override
                public void run() {
                    while(true) {
                        Future<String> future = futures.poll();
                        if(future != null && future.isDone()) {
                            // 处理业务
                            try {
                                System.out.println("消費者" + future.get());
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }.start();
        }
    
    }

    结果:

    ---------------------
    0
    消費者task done0
    消費者task done1
    消費者task done2
    消費者task done3
    消費者task done4
    消費者task done5
    消費者task done6
    消費者task done7
    消費者task done8
    消費者task done9

     示例2:用普通的list存放结果:

    public class ExecutorResultManager2 {
    
        public static void main(String[] args) {
            // 队列
            List<Future<String>> futures = new ArrayList<>();
            
            // 生产者
            new Thread() {
                @Override
                public void run() {
                    ExecutorService pool = Executors.newCachedThreadPool();
                    
                    for (int i=0; i< 10; i++) {
                        int index = i;
                        Future<String> submit = pool.submit(new Callable<String>() {
                            @Override
                            public String call() throws Exception {
                                TimeUnit.SECONDS.sleep(5);
                                return "task done" + index;
                            }
                        });
                        futures.add(submit);
                    }
                    
                    System.out.println("--消費者-----------------");
                    System.out.println(futures.size());
                    while(futures.size() > 0) {
                        Future<String> future = futures.get(0);
                        //System.out.println("future="+ future);
                        if(future.isDone()) {
                            // 处理业务
                            try {
                                System.out.println("消費者" + future.get());
                                futures.remove(0);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }.start();
        }
    
    }

    结果:

    --消費者-----------------
    10
    消費者task done0
    消費者task done1
    消費者task done2
    消費者task done3
    消費者task done4
    消費者task done5
    消費者task done6
    消費者task done7
    消費者task done8
    消費者task done9

    示例3:

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorCompletionService;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.TimeUnit;
    
    public class ExecutorResultManager3 {
    
        public static void main(String[] args) {
            final Random r = new Random();
            // 创建一个固定大小的线程池
            ExecutorService es = Executors.newFixedThreadPool(10);
            // 将所有处理结果提交到一个固定大小的队列(可不指定,默认创建一个无界队列)
            ExecutorCompletionService<String> ecs = new ExecutorCompletionService<String>(
                    es,new LinkedBlockingQueue<Future<String>>(1000));
            for (int i = 0; i < 10; i++) {
                //提交所有任务
                ecs.submit(new Callable<String>() {
                    @Override
                    public String call() throws Exception {
                        //模拟一个耗时操作
                        long l = r.nextInt(4000);
                        Thread.sleep(l);
                        return Thread.currentThread().getName() + "|" + l;
                    }
                });
                
                try {
                    //获得返回结果,3s超时(表示我们能够容忍的最大等待时间)
                    System.out.println(System.currentTimeMillis() + ecs.take().get(3, TimeUnit.SECONDS));
                } catch (Exception e) {
                    e.printStackTrace();
                }
                
            }
            es.shutdown();
        }
    
    }

    结果:

    1617599671725pool-1-thread-1|2967
    1617599674695pool-1-thread-2|2380
    1617599677076pool-1-thread-3|3308
    1617599680385pool-1-thread-4|399
    1617599680786pool-1-thread-5|1060
    1617599681847pool-1-thread-6|2106
    1617599683955pool-1-thread-7|1566
    1617599685521pool-1-thread-8|819
    1617599686342pool-1-thread-9|903
    1617599687246pool-1-thread-10|3417

  • 相关阅读:
    【MFC初学】
    【递归】【3月周赛1】【Problem B】
    不管ACM是不是屠龙之技
    【贪心+背包】【HDU2546】【饭卡】
    【精度问题】【HDU2899】Strange fuction
    【泛化物品】【HDU1712】【ACboy needs your help】
    【递推】【HDU2585】【hotel】
    【二进制拆分多重背包】【HDU1059】【Dividing】
    【水:最长公共子序列】【HDU1159】【Common Subsequence】
    【递推+矩阵快速幂】【HDU2604】【Queuing】
  • 原文地址:https://www.cnblogs.com/duanxz/p/14617990.html
Copyright © 2020-2023  润新知