Java并发CompletionService

510 阅读1分钟

一.简介

  • CompletionService的应用场景:批量提交异步任务。
  • CompletionService将线程池Executor和阻塞队列BlockingQueue融合在一起,使得批量异步任务的管理更简单。
  • CompletionService能够让异步任务的执行结果有序化,先执行完的先进入阻塞队列,避免无谓的等待。

二.API

接口

public interface CompletionService<V> {
// 提交Callable类型的任务
Future<V> submit(Callable<V> task);

// 提交Runnable类型的任务
Future<V> submit(Runnable task, V result);

// 获取并删除已完成状态的任务,如果没有则等待
Future<V> take() throws InterruptedException;
// 获取并删除已完成状态的任务,如果目前不存在这样的task,返回null
Future<V> poll();
// 获取并删除已完成状态的任务,必要时等待指定的等待时间(如果尚未存在)
Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException;
}

目前在 JDK8 中 CompletionService 接口只有一个实现类 ExecutorCompletionService

三.示例

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

public static void main(String[] args) throws InterruptedException, ExecutionException {
    ExecutorService service = Executors.newCachedThreadPool();
    ExecutorCompletionService<String> completionService = new ExecutorCompletionService<>(service);
    for (int i = 0; i < 100; i++) {
        completionService.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                int sleepValue = new Random().nextInt(5);
                System.out.println("sleep = " + sleepValue + ", name: " + Thread.currentThread().getName());
                TimeUnit.SECONDS.sleep(sleepValue);
                return "huhx: " + sleepValue + ", " + Thread.currentThread().getName();
            }
        });
    }
    for (int i = 0; i < 100; i++) {
        System.out.println(completionService.take().get());
    }
    service.shutdown();
}

结果

sleep = 3, name: pool-1-thread-72
sleep = 1, name: pool-1-thread-77
sleep = 1, name: pool-1-thread-73
sleep = 0, name: pool-1-thread-80
sleep = 0, name: pool-1-thread-75
sleep = 3, name: pool-1-thread-80
huhx: 0, pool-1-thread-12
sleep = 1, name: pool-1-thread-76
sleep = 2, name: pool-1-thread-60
huhx: 0, pool-1-thread-20
sleep = 3, name: pool-1-thread-79
huhx: 0, pool-1-thread-24

公众号

图片

微信号:bigdata_limeng