【併發程式設計】6.執行緒控制工具類
阿新 • • 發佈:2020-08-07
1.Future、Callable、FutureTask
執行緒池提供的submit方法
<T> Future<T> submit(Callable<T> task); //Callable call方法具有返回值,Future物件可以通過呼叫其get()方法來獲 取任務的執行結果。 <T> Future<T> submit(Runnable task, T result); //需要你注意的是Runnable介面的實現類Task聲明瞭一個有 參建構函式 Task(Result r) ,建立Task物件的時候傳入了result物件,這樣就能在類Task的run()方法 中對result進行各種操作了。result相當於主執行緒和子執行緒之間的橋樑,通過它主子執行緒可以共享資料。 Future<?> submit(Runnable task); //Runnable run方法沒有返回值 返回的Future僅用於判斷執行是否完成
在執行多個任務的時候,使用Java標準庫提供的執行緒池是非常方便的。我們提交的任務只需要實現Runnable介面,就可以讓執行緒池去執行。但是使用Runable介面無法獲取任務執行的結果。
於是Java提供了Callable介面,相比於Runable增加了返回值,並且Callable介面是一個泛型介面,可以返回指定型別的結果。
public interface Callable<V> {
V call() throws Exception;
}
將Callable 最為執行緒池執行任務的引數 通過返回值Future就可以獲得call方法的實現中返回的結果值:
public static void main(String[] args) throws Exception{ //初始化執行緒池,實際開發中不建議這麼做 ExecutorService threadPool = Executors.newFixedThreadPool(2); Future reuslt = threadPool.submit(new Callable<Integer>() { //匿名內部類實現Callable介面 @Override public Integer call() throws Exception { System.out.println("callable task run"); return 10; } }); //或者執行結果 會阻塞 Integer num = (Integer) reuslt.get(); System.out.println(num); threadPool.shutdown(); } //執行結果 //callable task run //10
Future
boolean cancel(boolean mayInterruptIfRunning); //取消任務的 方法 boolean isCancelled(); //判斷任務是否已取消 boolean isDone(); //判斷任務是否已結束 V get() throws InterruptedException, ExecutionException; //任務執行結果 當前執行緒阻塞 V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; //任務執行結果 超時機制 當前執行緒阻塞
FutureTask
//介面關係
public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();//介面的多繼承
}
//構造方法
FutureTask(Callable callable);
FutureTask(Runnable runnable, V result);
FutureTask實現了Runnable和Future介面,由於實現了Runnable 介面,所以可以將FutureTask物件作為任務提交給ThreadPoolExecutor去執行,也可以直接被Thread執行;
又因為實現了Future介面,所以也能用來獲得任務的執行結果。
//執行緒池執行FutureTask 並獲取結果
public static void main(String[] args) throws Exception{
// 建立
FutureTask futureTask = new FutureTask<>(()-> 1+2);
// 建立執行緒池
ExecutorService es = Executors.newCachedThreadPool();
// 提交
Future future = es.submit(futureTask);
// 獲取計算結果
Integer result = (Integer) futureTask.get();
System.out.println(result);
es.shutdown();
}
//直接由執行緒執行並且獲取結果
public static void main(String[] args) throws Exception{
// 建立
FutureTask futureTask = new FutureTask<>(()-> 1+2);
Thread th1 = new Thread(futureTask);
th1.start();
Integer result =(Integer) futureTask.get();
System.out.println(result);
}
2.CountDownLatch
CountDownLatch是Java 1.5提供的執行緒控制工具類,主要用來解決一個執行緒等待 多個執行緒的場景,可以類比旅遊團團長要等待所有的遊客到齊才能去下一個景點.
//構造方法 指定計數器
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
//計數器 -1
countDownLatch.countDown();//完成後計數器-1
///等待計數器為0
countDownLatch.await();
countDown()方法一般用於線上程池的任務中,注意進行異常捕獲,不然在await()時可能會造成一直阻塞。
ExecutorService executorService =Executors.newFixedThreadPool(3);
CountDownLatch cdl = new CountDownLatch(3);
executorService.execute(new Runnable() {
@Override
public void run() {
try {
function1();
} catch (Exception e) {
//異常處理
e.printStackTrace();
}
finally {
cdl.countDown();
}
}
});