Java多執行緒與併發程式設計——Condition、Callable&Future
阿新 • • 發佈:2021-09-06
前言
每天積累一點點,積跬步至千里。今天學習
JUC
包中的Condition、Callable&Future。
Condition等待與喚醒
JUC
提供了這麼多的工具類,目的是讓我們對於程式中多執行緒環境下,對執行緒的控制,Conditon
物件,用來讓指定的執行緒等待與喚醒,按照我們預期的順序執行,大白話就是,我們完全掌控執行緒的執行順序。注意:它必須和ReentrantLock
重入鎖配合使用。Condition
用於替代wait()/notify()
方法
notify
只能隨機喚醒等待的執行緒,而Condition
可以喚醒指定執行緒,這有利於更好的控制併發程式。
Condition核心方法
await()
阻塞當前執行緒,直到signal()喚醒signal()
喚醒被await()
的執行緒,從中斷處繼續執行signalAll()
喚醒所有被await()
阻塞的執行緒
程式碼示例
- 建立三個執行緒,分別列印
1
、2
、3
,為了效果明顯加了1000ms
睡眠,正常情況下按順序列印肯定是1
、2
、3
- 但是現在我們想要列印
3
、1
、2
,這時就可以利用Condition
來實現控制,看下面程式碼
publicclassConditionSample{ publicstaticvoidmain(String[]args)throwsInterruptedException{ ReentrantLocklock=newReentrantLock(); Conditionc1=lock.newCondition(); Conditionc2=lock.newCondition(); newThread(()->{ lock.lock(); try{ c1.await();//阻塞當前執行緒 Thread.sleep(1000); System.out.println(1); }catch(InterruptedExceptione){ e.printStackTrace(); }finally{ lock.unlock(); } }).start(); newThread(()->{ lock.lock(); try{ c2.await();//阻塞當前執行緒 Thread.sleep(1000); System.out.println(2); }catch(InterruptedExceptione){ e.printStackTrace(); }finally{ lock.unlock(); } }).start(); newThread(()->{ lock.lock(); try{ Thread.sleep(1000); System.out.println(3); c1.signal(); c2.signal(); }catch(InterruptedExceptione){ e.printStackTrace(); }finally{ lock.unlock(); } }).start(); } }
我們通過
ReentrantLock
物件建立了2
個Condition
物件c1
、c2
.相當於兩個標記鎖,分別加在列印1
和2
的執行緒上,等3
列印完成,再去控制先喚醒哪個,先喚醒哪個則哪個列印輸出,實現預期效果。
Callable&Future
- Callable和Runnable一樣用來建立執行緒,區別在於Callable有返回值並且可以丟擲異常
- Future是一個介面。它用於表示非同步計算的結果。提供了檢查計算是否完成的方法,以等待計算的完成,並獲取計算的結果。
程式碼示例
獲取
10000
以內所有的質數,單執行緒迴圈查詢的做法這裡就不做介紹了,看下面示例程式碼,我們可以通過多執行緒的方式去判斷是否為質數,然後將結果接收返回。這裡獲取質數的方法比較簡單,如果換成更為複雜的邏輯,多執行緒的效率優勢就會很明顯了。
publicclassFutureSample{ publicstaticvoidmain(String[]args){ ExecutorServiceexecutorService=Executors.newFixedThreadPool(10); for(inti=2;i<=10000;i++){ Computorc=newComputor(); c.setNum(i); Future<Boolean>result=executorService.submit(c); try{ Booleanr=result.get(); if(r){ System.out.println(c.getNum()); } }catch(InterruptedException|ExecutionExceptione){ e.printStackTrace(); } } executorService.shutdown(); } } classComputorimplementsCallable<Boolean>{ privateIntegernum; publicIntegergetNum(){ returnnum; } publicvoidsetNum(Integernum){ this.num=num; } @Override publicBooleancall()throwsException{ booleanisprime=true; for(inti=2;i<num;i++){ if(num%i==0){ isprime=false; break; } } returnisprime; } }
Future
是對用於計算的執行緒進行監聽,因為計算是在其他執行緒中執行的,所以這個返回結果的過程是非同步的executorService.submit(c);
將c
物件提交給執行緒池,如有空閒執行緒立即執行裡面的call
方法result.get();
用於獲取返回值,如果執行緒內部的call
沒有執行完成,則進入等待狀態,直到計算完成