CountDownLatch、CyclicBarrier和Semaphore這三個并發輔助類,可以在線程中呼叫,使得線程暫停等,但各有不同。
1、初始化,并傳入計數器
2、向不同的線程傳入CountDownLatch實例
3、如果在某一線程中呼叫await(),則此線程被掛起,直到計數器為0,才往下執行
4、如果在某一線程中呼叫countDown(),計數器減1
5、最終如果計數器值為0時,則CountDownLatch實例不再起作用了,即為一次性的
1、初始化,并傳入計數器值,也可傳入一個Runnable類,會在計數器為0時,被執行
2、向不同的線程傳入CyclicBarrier實例
3、如果在某一線程中呼叫await(),則此線程被掛起,直到計數器為0,才往下執行
4、其他線程呼叫await(),則此線程被掛起,直到計數器為0,才往下執行
5、最終如果計數器值為0時,則CyclicBarrier實例會將計數器值恢復,又可重用
1、初始化,并傳入計數器值
2、向不同的線程傳入Semaphore實例
3、如果在某一線程中呼叫acquire(),則Semaphore實例會將計數器值減1,如果計數器值為-1,則將計數器值置為0,此線程被掛起,直到計數器值大于1時,才往下執行
4、此線程需呼叫release(),使得計數器值+1,以便其他線程在計數器值為0時不受阻
CountDownLatch 例子:
public class Test {
public static void main(String[] args) {
final CountDownLatch latch =
new CountDownLatch(2);
new Thread(){
public void run() {
try {
System.out.println("子線程"+Thread.currentThread().getName()+"正在執行");
Thread.sleep(3000);
System.out.println("子線程"+Thread.currentThread().getName()+"執行完畢");
latch.countDown();
}
catch (InterruptedException e) {
e.printStackTrace();
}
};
}.start();
new Thread(){
public void run() {
try {
System.out.println("子線程"+Thread.currentThread().getName()+"正在執行");
Thread.sleep(3000);
System.out.println("子線程"+Thread.currentThread().getName()+"執行完畢");
latch.countDown();
}
catch (InterruptedException e) {
e.printStackTrace();
}
};
}.start();
try {
System.out.println("等待2個子線程執行完畢

");
latch.await();
System.out.println("2個子線程已經執行完畢");
System.out.println("繼續執行主線程");
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
結果:
線程Thread-0正在執行
線程Thread-1正在執行
等待2個子線程執行完畢

線程Thread-0執行完畢
線程Thread-1執行完畢
2個子線程已經執行完畢
繼續執行主線程
CyclicBarrier例子:
public class Test {
public static void main(String[] args) {
int N = 4;
CyclicBarrier barrier =
new CyclicBarrier(N,
new Runnable() {
@Override
public void run() {
System.out.println("當前線程"+Thread.currentThread().getName());
}
});
for(
int i=0;i<N;i++)
new Writer(barrier).start();
}
static class Writer
extends Thread{
private CyclicBarrier cyclicBarrier;
public Writer(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
System.out.println("線程"+Thread.currentThread().getName()+"正在寫入數據

");
try {
Thread.sleep(5000);
//以睡眠來模擬寫入數據操作
System.out.println("線程"+Thread.currentThread().getName()+"寫入數據完畢,等待其他線程寫入完畢");
cyclicBarrier.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
catch(BrokenBarrierException e){
e.printStackTrace();
}
System.out.println("所有線程寫入完畢,繼續處理其他任務

");
}
}
}
執行結果:
線程Thread-0正在寫入數據

線程Thread-1正在寫入數據

線程Thread-2正在寫入數據

線程Thread-3正在寫入數據

線程Thread-0寫入數據完畢,等待其他線程寫入完畢
線程Thread-1寫入數據完畢,等待其他線程寫入完畢
線程Thread-2寫入數據完畢,等待其他線程寫入完畢
線程Thread-3寫入數據完畢,等待其他線程寫入完畢
當前線程Thread-3
所有線程寫入完畢,繼續處理其他任務

所有線程寫入完畢,繼續處理其他任務

所有線程寫入完畢,繼續處理其他任務

所有線程寫入完畢,繼續處理其他任務

Semaphore例子:
public class Test {
public static void main(String[] args) {
int N = 8;
//工人數
Semaphore semaphore =
new Semaphore(5);
//機器數目
for(
int i=0;i<N;i++)
new Worker(i,semaphore).start();
}
static class Worker
extends Thread{
private int num;
private Semaphore semaphore;
public Worker(
int num,Semaphore semaphore){
this.num = num;
this.semaphore = semaphore;
}
@Override
public void run() {
try {
semaphore.acquire();
System.out.println("工人"+
this.num+"占用一個機器在生產

");
Thread.sleep(2000);
System.out.println("工人"+
this.num+"釋放出機器");
semaphore.release();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
執行結果:
工人0占用一個機器在生產

工人1占用一個機器在生產

工人2占用一個機器在生產

工人4占用一個機器在生產

工人5占用一個機器在生產

工人0釋放出機器
工人2釋放出機器
工人3占用一個機器在生產

工人7占用一個機器在生產

工人4釋放出機器
工人5釋放出機器
工人1釋放出機器
工人6占用一個機器在生產

工人3釋放出機器
工人7釋放出機器
工人6釋放出機器
https://www.cnblogs.com/dolphin0520/p/3920397.html