wait()、notify()和notifyAll()是Object類中的方法:
為什麼wait()等方法是在Object中而不是Thread中呢?
同理,wait(),notify()是對等待這個Object(鎖)的執行緒進行阻塞,喚醒等操作的,當然也要放在Object中
假設,wait(),notify()放在Thead中,那麼Thread可能等待很多個鎖,操作起來也很複雜
如果呼叫某個物件的wait()方法,當前執行緒必須擁有這個物件的monitor(即鎖),因此呼叫wait()方法必須在同步塊或者同步方法中進行(synchronized塊或者synchronized方法)
呼叫某個物件的wait()方法,相當於讓當前執行緒交出此物件的monitor,然後進入等待狀態,等待後續再次獲得此物件的鎖(Thread類中的sleep方法使當前執行緒暫停執行一段時間,從而讓其他執行緒有機會繼續執行,但它並不釋放物件鎖)
同樣地,呼叫某個物件的notify()方法,當前執行緒也必須擁有這個物件的monitor,因此呼叫notify()方法必須在同步塊或者同步方法中進行(synchronized塊或者synchronized方法)
進階一訊號量
Java 提供了經典訊號量(Semaphore)的實現,通過控制一定數量的允許(permit)的方式,來達到限制通用資源訪問的目的。 你可以想象一下這個場景,在車站、機場等計程車時,當很多空計程車就位時,為防止過度擁擠,排程員指揮排隊,等待坐車的隊伍一次進來5個人上車, 等這5個人坐車出發,再放進去下一批 當訊號量的大小為1時,與synchronized沒有區別
public class SemaphoreTest {
private static Semaphore semaphore = new Semaphore(5);
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new CarWorker(semaphore).start();
}
}
}
class CarWorker extends Thread {
private Semaphore semaphore;
public CarWorker(Semaphore semaphore) {
this.semaphore = semaphore;
}
@Override
public void run() {
try {
out.println(Thread.currentThread() + " waiting permitted");
semaphore.acquire();
out.println(Thread.currentThread() + " on car !");
Thread.sleep(10000);
} catch (Exception e) {
} finally {
out.println(Thread.currentThread() + " release permitted");
semaphore.release();
}
}
}
複製程式碼
進階-CountDownLatch
一次性使用的計數器,當CountDownLatch中數值為0時,所有await的執行緒得到喚醒 特別適合於A執行緒需要等待B和C執行緒的結果作為引數的這種場景
public class CountDownLatchTest {
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 0; i < 5; i++) {
new FirstBatchPassenger(countDownLatch).start();
}
for (int i = 0; i < 5; i++) {
new SecondBatchPassenger(countDownLatch).start();
}
while (countDownLatch.getCount() != 1) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
out.println("MainThread countDown!");
countDownLatch.countDown();
}
}
class FirstBatchPassenger extends Thread {
private CountDownLatch countDownLatch;
public FirstBatchPassenger(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
out.println("FirstBatchPassenger Executed!");
countDownLatch.countDown();
}
}
class SecondBatchPassenger extends Thread {
private CountDownLatch countDownLatch;
public SecondBatchPassenger(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try {
countDownLatch.await();
out.println("SecondBatchPassenger Executed!");
} catch (InterruptedException e) {
}
}
}
複製程式碼
輸出:
FirstBatchPassenger Executed!
FirstBatchPassenger Executed!
FirstBatchPassenger Executed!
FirstBatchPassenger Executed!
FirstBatchPassenger Executed!
MainThread countDown!
SecondBatchPassenger Executed!
SecondBatchPassenger Executed!
SecondBatchPassenger Executed!
SecondBatchPassenger Executed!
SecondBatchPassenger Executed!
複製程式碼
進階三-CyclicBarrier
觸發屏障,當await自動達到屏障數量時,觸發屏障操作。可重複使用!
public class CyclicBarrierTest {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> out.println("Action GO!"));
for (int i = 0; i<6;i++){
new CyclicBarrierWorker(cyclicBarrier).start();
}
}
}
class CyclicBarrierWorker extends Thread {
private CyclicBarrier cyclicBarrier;
public CyclicBarrierWorker(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
out.println("Executed!");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
} catch (BrokenBarrierException e) {
}
}
}
複製程式碼
輸出:
Executed!
Executed!
Executed!
Action GO!
Executed!
Action GO!
Executed!
Executed!
Action GO!
複製程式碼