一、概述
同时并发的按照不同的方式处理数据,需要对处理后的结果在处理或用作响应第三方请求。
这时候,有两种常见的需求。
- 第一种,只要有一个处理有结果,就立刻结束其他还在运行中的处理方式
- 第二种,等待所有处理有结果后再处理
二、处理方案
1.线程处理返回结果
一般开发中,使用多线程,最常见的就是:1.实现Runnable接口;2.继承Thread类。
但是run方法是没有返回结果,很难满足我们的需求。这时,常用的办法就是实现Callable接口
Callable接口提供了一个call方法入口,我们可以通过实现call方法,来执行任务;这个接口支持泛型,可以通过泛型参数,来获取想要的结果类型
2.关闭线程池
可以通过调用线程池的shutdown或shutdowNow方法来关闭线程池,但是它们的实现原理不同。
shutdown的原理只是将线程池的状态设置SHUTDOWN状态,然后中断没有开始执行任务的线程。
shutdownNow的原理是遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程,所以需要注意一点,如果存在无法响应中断的任务,可能永远无法终止。shutdownNow会首先将线程池的状态设置成STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表。
三、具体实现样例
1 import org.slf4j.Logger; 2 import org.slf4j.LoggerFactory; 3 4 import java.util.ArrayList; 5 import java.util.List; 6 import java.util.Random; 7 import java.util.concurrent.Callable; 8 import java.util.concurrent.ExecutorService; 9 import java.util.concurrent.Executors; 10 import java.util.concurrent.Future; 11 12 /** 13 * Created by wy_ms on 2017/04/12. 14 */ 15 public class TaskCallable implements Callable<String> { 16 17 private static Logger logger = LoggerFactory.getLogger(TaskCallable.class); 18 String name; 19 int sleep; 20 public TaskCallable(String name, int sleep) { 21 this.name = name; 22 this.sleep = sleep; 23 } 24 25 @Override 26 public String call() throws Exception { 27 logger.info("[{}]任务开始执行",name); 28 int random = new Random().nextInt(100); 29 random = random + 1; 30 logger.info("[{}]任务开始睡眠[{}]秒",name,random); 31 Thread.sleep(random*1000); 32 logger.info("[{}]任务执行结束",name); 33 return name; 34 } 35 36 public static void main(String[] args) throws Exception { 37 38 ExecutorService pool = Executors.newFixedThreadPool(2); 39 List<Future<String>> results = new ArrayList<>(); 40 for (int i = 1; i < 3; i++) { 41 results.add(pool.submit(new TaskCallable("the "+i,i))); 42 } 43 // pool.shutdown(); 44 Future<String> done = null; 45 int i = 0; 46 while (null==done&&i<100) { 47 Thread.sleep(1000); 48 logger.info("开始等待处理结果"); 49 for (Future f: results) { 50 if (f.isDone()) { 51 done=f; 52 logger.info("处理已经有了结果"); 53 break; 54 } 55 } 56 i++; 57 } 58 pool.shutdownNow(); 59 System.out.println(done.get()); 60 61 } 62 }