爲何wait()等方法是在Object中而不是Thread中呢?bash
同理,wait(),notify()是對等待這個Object(鎖)的線程進行阻塞,喚醒等操做的,固然也要放在Object中ide
假設,wait(),notify()放在Thead中,那麼Thread可能等待不少個鎖,操做起來也很複雜ui
若是調用某個對象的wait()方法,當前線程必須擁有這個對象的monitor(即鎖),所以調用wait()方法必須在同步塊或者同步方法中進行(synchronized塊或者synchronized方法)this
調用某個對象的wait()方法,至關於讓當前線程交出此對象的monitor,而後進入等待狀態,等待後續再次得到此對象的鎖(Thread類中的sleep方法使當前線程暫停執行一段時間,從而讓其餘線程有機會繼續執行,但它並不釋放對象鎖)spa
一樣地,調用某個對象的notify()方法,當前線程也必須擁有這個對象的monitor,所以調用notify()方法必須在同步塊或者同步方法中進行(synchronized塊或者synchronized方法)線程
Java 提供了經典信號量(Semaphore)的實現,經過控制必定數量的容許(permit)的方式,來達到限制通用資源訪問的目的。 你能夠想象一下這個場景,在車站、機場等出租車時,當不少空出租車就位時,爲防止過分擁擠,調度員指揮排隊,等待坐車的隊伍一次進來5我的上車, 等這5我的坐車出發,再放進去下一批 當信號量的大小爲1時,與synchronized沒有區別code
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中數值爲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!
複製代碼
觸發屏障,當await自動達到屏障數量時,觸發屏障操做。可重複使用!get
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!
複製代碼