【并发编程】- 线程池使用ExecutorCompletionService的take()方法具有阻塞特性

155 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第16天,点击查看活动详情

ExecutorCompletionService的take()方法具有阻塞特性

修改运行类执行代码如下:

@Slf4j
public class FutureRun {
    public static void main(String[] args) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
        FutureCallable g1 = new FutureCallable("G1", 5000L);
        FutureCallable g2 = new FutureCallable("G2", 4000L);
        FutureCallable g3 = new FutureCallable("G3", 3000L);
        FutureCallable g4 = new FutureCallable("G4", 2000L);
        FutureCallable g5 = new FutureCallable("G5", 1000L);

        ArrayList<Callable> callableArrayList = new ArrayList<>();
        callableArrayList.add(g1);
        callableArrayList.add(g2);
        callableArrayList.add(g3);
        callableArrayList.add(g4);
        callableArrayList.add(g5);

        ArrayList<Future> futureArrayList = new ArrayList<>();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
        //使用CompletionService
        ExecutorCompletionService executorCompletionService = new ExecutorCompletionService(threadPoolExecutor);
        for (int i = 0; i < 5 ; i++) {
            executorCompletionService.submit(callableArrayList.get(i));
        }
        for (int i = 0; i < 6 ; i++) {
            try {
                log.info("等待输出第{}个",i+1);
                log.info("返回值:{}",executorCompletionService.take().get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果如下:

[pool-1-thread-5] INFO com.ozx.concurrentprogram.executor.service.FutureCallable - 用户名:G5

[pool-1-thread-3] INFO com.ozx.concurrentprogram.executor.service.FutureCallable - 用户名:G3

[pool-1-thread-2] INFO com.ozx.concurrentprogram.executor.service.FutureCallable - 用户名:G2

[pool-1-thread-4] INFO com.ozx.concurrentprogram.executor.service.FutureCallable - 用户名:G4

[main] INFO com.ozx.concurrentprogram.executor.controller.FutureRun - 等待输出第1个

[pool-1-thread-1] INFO com.ozx.concurrentprogram.executor.service.FutureCallable - 用户名:G1

[main] INFO com.ozx.concurrentprogram.executor.controller.FutureRun - 返回值:G5

[main] INFO com.ozx.concurrentprogram.executor.controller.FutureRun - 等待输出第2个

[main] INFO com.ozx.concurrentprogram.executor.controller.FutureRun - 返回值:G4

[main] INFO com.ozx.concurrentprogram.executor.controller.FutureRun - 等待输出第3个

[main] INFO com.ozx.concurrentprogram.executor.controller.FutureRun - 返回值:G3

[main] INFO com.ozx.concurrentprogram.executor.controller.FutureRun - 等待输出第4个

[main] INFO com.ozx.concurrentprogram.executor.controller.FutureRun - 返回值:G2

[main] INFO com.ozx.concurrentprogram.executor.controller.FutureRun - 等待输出第5个

[main] INFO com.ozx.concurrentprogram.executor.controller.FutureRun - 返回值:G1

[main] INFO com.ozx.concurrentprogram.executor.controller.FutureRun - 等待输出第6个

从运行结果看出将循环次数修改为6次,线程池执行5个任务后一直在等待阻塞着,所以在CompletionService接口中如果当前没有任务被执行完,CompletionService.take().get()的方法还是处于阻塞状态。

ExecutorCompletionService使用take()方法

take()方法取得最先完成任务的Future对象,哪个任务先执行时间最短哪个任务最先返回。