CompletionService的使用场景以及示例

CompletionService用来异步获取ExecutorService的执行结果,因为用了阻塞队列,所以先出的结果先获取。目前只有一个实现类ExecutorCompletionService。

下面是示例Demo:场景是,三个耗时操作分别进行,最后将处理结果给主线程的另一个子线程保存结果。

结构为

CompletionServiceDemo.java
package com.example.demo.concurrent.completionservice;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

@Slf4j
public class CompletionServiceDemo {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        BlockingQueue blockingQueue = new LinkedBlockingQueue(10);
        CompletionService completionService = new ExecutorCompletionService(executorService,blockingQueue);

        completionService.submit(new MyCallableA());
        completionService.submit(new MyCallableB());
        completionService.submit(new MyCallableC());
        try {
            for (int i = 0; i < 3 ; i++) {
                Result result = (Result) completionService.take().get();
                executorService.execute(new MyThread(result));
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

}
MyCallableA.java,MyCallableB.java,MyCallableC.java三个类代码一样,名称不同。
package com.example.demo.concurrent.completionservice;

import lombok.extern.slf4j.Slf4j;

import java.util.Random;
import java.util.concurrent.TimeUnit;

@Slf4j
public class MyThread extends Thread {
    private Result result;
    public MyThread(Result rs) {
        result = rs;
    }

    @Override
    public void run() {
        log.info("执行线程保存处理结果-----开始----");
        try {
            TimeUnit.SECONDS.sleep(new Random().nextInt(5));
            log.info("执行线程保存处理结果-----保存结果:{}----",result.toString());
            log.info("执行线程保存处理结果-----结束----");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

MyThread.java用于执行处理的结果。 

package com.example.demo.concurrent.completionservice;

import lombok.extern.slf4j.Slf4j;

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

@Slf4j
public class MyCallableA implements Callable<Result> {
    @Override
    public Result call() throws Exception {
        log.info("执行MyCallableA-----");
        TimeUnit.SECONDS.sleep(new Random().nextInt(10));
        Result result = new Result("MyCallableA","19");
        return result;
    }
}

 另一个是结果对象Result.java

package com.example.demo.concurrent.completionservice;

import lombok.Data;

@Data
public class Result {
    private String name;
    private String age;

    public Result(String name, String age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Result{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }
}

执行结果如下:

Connected to the target VM, address: '127.0.0.1:62249', transport: 'socket'
00:16:41.462 [pool-1-thread-3] INFO com.example.demo.concurrent.completionservice.MyCallableC - 执行MyCallableC-----
00:16:41.462 [pool-1-thread-1] INFO com.example.demo.concurrent.completionservice.MyCallableA - 执行MyCallableA-----
00:16:41.462 [pool-1-thread-2] INFO com.example.demo.concurrent.completionservice.MyCallableB - 执行MyCallableB-----
00:16:46.483 [pool-1-thread-1] INFO com.example.demo.concurrent.completionservice.MyThread - 执行线程保存处理结果-----开始----
00:16:47.482 [pool-1-thread-3] INFO com.example.demo.concurrent.completionservice.MyThread - 执行线程保存处理结果-----开始----
00:16:48.482 [pool-1-thread-2] INFO com.example.demo.concurrent.completionservice.MyThread - 执行线程保存处理结果-----开始----
00:16:48.482 [pool-1-thread-2] INFO com.example.demo.concurrent.completionservice.MyThread - 执行线程保存处理结果-----保存结果:Result{name='MyCallableB', age='19'}----
00:16:48.484 [pool-1-thread-2] INFO com.example.demo.concurrent.completionservice.MyThread - 执行线程保存处理结果-----结束----
00:16:49.485 [pool-1-thread-1] INFO com.example.demo.concurrent.completionservice.MyThread - 执行线程保存处理结果-----保存结果:Result{name='MyCallableA', age='19'}----
00:16:49.485 [pool-1-thread-1] INFO com.example.demo.concurrent.completionservice.MyThread - 执行线程保存处理结果-----结束----
00:16:51.483 [pool-1-thread-3] INFO com.example.demo.concurrent.completionservice.MyThread - 执行线程保存处理结果-----保存结果:Result{name='MyCallableC', age='19'}----
00:16:51.483 [pool-1-thread-3] INFO com.example.demo.concurrent.completionservice.MyThread - 执行线程保存处理结果-----结束----

 

这里有几个对象很重要。

//真正执行线程的Service
ExecutorService executorService = Executors.newFixedThreadPool(3);
//阻塞队列,用来保存异步线程处理结果
BlockingQueue blockingQueue = new LinkedBlockingQueue(10);
//把真正处理异步线程的对象与阻塞队列关联起来
CompletionService completionService = new ExecutorCompletionService(executorService,blockingQueue);

最后通过

completionService.take().get();

获取到结果,分别处理。

 

注意:

1.先处理完的将先放到队列中

2.如果不新建阻塞队列,默认会创建一个new LinkedBlockingQueue<Future<V>>(),大小为Integer.MAX_VALUE。

3.submit方式有两种

submit(Callable<V> task)或者
submit(Runnable task, V result)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞翔的咩咩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值