工作中,遇到很多情況需要使用線程,或者線程池。但往往我們需要等待線程池執行結束後,使用執行結束後的數據做下一步操作。
很多人提供的輪詢,這樣無形增加服務器的壓力。
現在使用JDK 1.5 提供線程池ExecutorService類配合Future接口來實現。 Future接口是Java標準API的一部分,在java.util.concurrent包中。Future接口是Java線程Future模式的實現,可以來進行異步計算。
Future模式可以這樣來描述:我有一個任務,提交給了Future,Future替我完成這個任務。期間我自己可以去做任何想做的事情。一段時間之後,我就便可以從Future那兒取出結果。就相當於下了一張訂貨單,一段時間後可以拿着提訂單來提貨,這期間可以幹別的任何事情。其中Future 接口就是訂貨單,真正處理訂單的是Executor類,它根據Future接口的要求來生產產品。
Future接口提供方法來檢測任務是否被執行完,等待任務執行完獲得結果,也可以設置任務執行的超時時間。這個設置超時的方法就是實現Java程序執行超時的關鍵。
Future接口是一個泛型接口,嚴格的格式應該是Future<V>,其中V代表了Future執行的任務返回值的類型。 Future接口的方法介紹如下:
- boolean cancel (boolean mayInterruptIfRunning) 取消任務的執行。參數指定是否立即中斷任務執行,或者等等任務結束
- boolean isCancelled () 任務是否已經取消,任務正常完成前將其取消,則返回 true
- boolean isDone () 任務是否已經完成。需要注意的是如果任務正常終止、異常或取消,都將返回true
- V get () throws InterruptedException, ExecutionException 等待任務執行結束,然後獲得V類型的結果。InterruptedException 線程被中斷異常, ExecutionException任務執行異常,如果任務被取消,還會拋出
CancellationException
- V get (long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException 同上面的get功能一樣,多了設置超時時間。參數timeout指定超時時間,uint指定時間的單位,在枚舉類TimeUnit中有相關的定義。如果計算超時,將拋出TimeoutException
- void shutdown(); //停止線程
- <T> Future<T> submit(Callable<T> task);
Future的實現類有java.util.concurrent.FutureTask<V>即 javax.swing.SwingWorker<T,V>。通常使用FutureTask來處理我們的任務。FutureTask類同時又實現了Runnable接口,所以可以直接提交給Executor執行。
package Thread;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class TestThread {
public static void main(String[] args) {
TestThread t =new TestThread();
t.Test();
}
public void Test(){
ExecutorService executorService = Executors.newFixedThreadPool(10);//線程池的大小
List<Future<List<Integer>>> results = new ArrayList<Future<List<Integer>>>();//具體創建的線程對象
for (int i =0; i< 4; i++) {
ThreadObject v = new ThreadObject(i);
Future<List<Integer>> result = executorService.submit(v);//執行線程
results.add(result);//將此線程添加到線程list中
}
for(Future<List<Integer>> result : results){
List<Integer> list = new ArrayList<Integer>();
try {
list = result.get();//通過GET 獲取線程的執行結果,如果沒有執行結束,則此get方法會處於等待狀態,知道線程執行結束
} catch (Exception e) {
}
System.out.println(list.toString());
System.out.println("END");
}
executorService.shutdown();//這裏,則線程池中的線程都已經執行完畢了。所以關閉線程池
}
}
package Thread;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
public class ThreadObject implements Callable<List<Integer>>{
private int i;
public ThreadObject(int i) {
this.i = i;
System.out.println("This is " + i);
}
@Override
public List<Integer> call() throws Exception {
List<Integer> list = new ArrayList<Integer>();
for (int i =0; i< 10; i++) {
list.add(i);
System.out.println(this.i + " Thread: " + i);
//Thread.sleep(100);
}
return list;
}
}