在开发中为了提高系统处理效率,用到多线程,多线程不细讲,主要说明一下多线程执行后拿到返回结果,这个也是部分新人容易忽视的,刚好最近在使用记录下。
大致步骤如下:
- 创建一个线程池
- 创建一个任务继承Callable接口
- 线程池提交执行第二步创建的任务
- 获取任务执行的结果,这步详细说明
代码示例如下:
第二步:任务类
public class Task implements Callable {
private int time;
private String name;
public Task(int time,String name) {
this.time = time ;
this.name = name;
}
@Override
public String call() throws Exception {
TimeUnit.SECONDS.sleep(this.time) ;
return name+"---success";
}
}
调用:
public String upload1() throws Exception {
ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10)) ;
CompletionService<String> cs = new ExecutorCompletionService<>(pool) ;
cs.submit(new Task(3, "name" + 3)) ;
cs.submit(new Task(1, "name" + 1)) ;
cs.submit(new Task(2, "name" + 2)) ;
for (int i = 0; i < 3; i++) {
String s = cs.take().get();
log.info("获取返回结果---"+s);
}
pool.shutdown();
return "success";
}
执行:
2022-07-14 18:43:49.060 INFO 18016 --- [nio-8080-exec-8] c.e.d.controller.EasyExcelBIoController : 获取返回结果---name3---success
2022-07-14 18:43:49.060 INFO 18016 --- [nio-8080-exec-8] c.e.d.controller.EasyExcelBIoController : 获取返回结果---name1---success
2022-07-14 18:43:49.060 INFO 18016 --- [nio-8080-exec-8] c.e.d.controller.EasyExcelBIoController : 获取返回结果---name2---success
分析:通过结果可以看到,代码执行任务的顺序是:3-1-2,获取结果的时候返回也是按照执行的顺序。这里有一个缺陷,主线程会一直等待任务3的结果,任务3需要执行3秒,任务1和任务2执行完了,却被任务3阻塞住了,当然部分场景这样也可以。
因此下面带来异步获取任务,也是本文的核心。
调用:
public String upload1() throws Exception {
ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10)) ;
CompletionService<String> cs = new ExecutorCompletionService<>(pool) ;
cs.submit(new Task(3, "name" + 3)) ;
cs.submit(new Task(1, "name" + 1)) ;
cs.submit(new Task(2, "name" + 2)) ;
for (int i = 0; i < 3; i++) {
String s = cs.take().get();
log.info("获取返回结果---"+s);
}
pool.shutdown();
return "success";
}
执行:
2022-07-14 18:48:52.793 INFO 18016 --- [io-8080-exec-10] c.e.d.controller.EasyExcelBIoController : 获取返回结果---name1---success
2022-07-14 18:48:53.797 INFO 18016 --- [io-8080-exec-10] c.e.d.controller.EasyExcelBIoController : 获取返回结果---name2---success
2022-07-14 18:48:54.803 INFO 18016 --- [io-8080-exec-10] c.e.d.controller.EasyExcelBIoController : 获取返回结果---name3---success
可以看到,拿到返回结果是按照执行速度快慢返回的,避免了第一种阻塞的方式,这种方式也叫做异步获取。
根据不同场景使用不同的方式,也不是哪一种就是最好的。