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

posted on 2021-04-05 11:08  duanxz  阅读(472)  评论(0编辑  收藏  举报