一、概述
同時並發的按照不同的方式處理數據,需要對處理后的結果在處理或用作響應第三方請求。
這時候,有兩種常見的需求。
- 第一種,只要有一個處理有結果,就立刻結束其他還在運行中的處理方式
- 第二種,等待所有處理有結果后再處理
二、處理方案
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 }