線程同步計(jì)數(shù)器
利用線程池進(jìn)行線程開發(fā)使用時(shí),因join方法使用不便而引入了線程同步計(jì)數(shù)器。
CountDownLatch計(jì)數(shù)器
通過代理變量sync 實(shí)現(xiàn)AbstractQueuedSynchronizer接口。
CountDownLatch是通過一個(gè)計(jì)數(shù)器來實(shí)現(xiàn)的,計(jì)數(shù)器的初始值為線程的數(shù)量。每當(dāng)一個(gè)線程完成了自己的任務(wù)后,計(jì)數(shù)器的值就會(huì)減1,當(dāng)計(jì)數(shù)器值到達(dá)0時(shí),它表示所有的線程已經(jīng)完成了任務(wù),然后在閉鎖上等待的線程就可以恢復(fù)執(zhí)行任務(wù)。
CountDownLatch中主要方法如下:
public CountDownLatch(int count);//,構(gòu)造函數(shù)中的count(計(jì)數(shù)器)實(shí)際上就是閉鎖需要等待的線程數(shù)量,這個(gè)值只能被設(shè)置一次,而且CountDownLatch沒有提供任何機(jī)制去重新設(shè)置這個(gè)計(jì)數(shù)值。
public void countDown();//每調(diào)用一次這個(gè)方法,在構(gòu)造函數(shù)中初始化的count值就減1,通知機(jī)制是此方法來完成的。
public void await() throws InterruptedException//調(diào)用此方法的當(dāng)前線程會(huì)一直阻塞,直到計(jì)時(shí)器的值為0。
簡(jiǎn)單使用
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(11);
ExecutorService service = Executors.newFixedThreadPool(7);
int i =1;
Runnable runnable = ()->{
System.out.println("countDownLatch前"+Thread.currentThread().getName());
countDownLatch.countDown();
/*try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}*/
System.out.println("countDownLatch后"+Thread.currentThread().getName());
};
for(int j = 0; j < 10;j++)
service.execute(runnable);
countDownLatch.await();
System.out.println("hello"+countDownLatch.getCount());
service.shutdown();
}
CyclicBarrier回環(huán)屏障
通過代理的獨(dú)占鎖實(shí)現(xiàn)
public CyclicBarrier(int parties);
public CyclicBarrier(int parties, Runnable barrierAction);
public int await() throws InterruptedException, BrokenBarrierException
public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException
線程調(diào)用 await() 表示自己已經(jīng)到達(dá)柵欄
BrokenBarrierException 表示柵欄已經(jīng)被破壞,破壞的原因可能是其中一個(gè)線程 await() 時(shí)被中斷或者超時(shí)
所有線程會(huì)等待全部線程到達(dá)柵欄之后才會(huì)繼續(xù)執(zhí)行,并且最后到達(dá)的線程會(huì)完成 Runnable 的任務(wù)。
CyclicBarrier和CountDownLatch的區(qū)別
CountDownLatch的計(jì)數(shù)器只能使用一次,而CyclicBarrier的計(jì)數(shù)器可以使用reset()方法重置,可以使用多次,所以CyclicBarrier能夠處理更為復(fù)雜的場(chǎng)景;
CyclicBarrier還提供了一些其他有用的方法,比如getNumberWaiting()方法可以獲得CyclicBarrier阻塞的線程數(shù)量,isBroken()方法用來了解阻塞的線程是否被中斷;
CountDownLatch允許一個(gè)或多個(gè)線程等待一組事件的產(chǎn)生,而CyclicBarrier用于等待其他線程運(yùn)行到柵欄位置。
Semaphore信號(hào)量
通過代理變量sync 實(shí)現(xiàn)AbstractQueuedSynchronizer接口。
Semaphore 是一個(gè)計(jì)數(shù)信號(hào)量,必須由獲取它的線程釋放。
常用于限制可以訪問某些資源的線程數(shù)量,例如通過 Semaphore 限流。
Semaphore 只有3個(gè)操作:初始化 增加 減少
Semaphore(int permits);//構(gòu)造方法,創(chuàng)建具有給定許可數(shù)的計(jì)數(shù)信號(hào)量并設(shè)置為非公平信號(hào)量。
Semaphore(int permits,boolean fair);//構(gòu)造方法,當(dāng)fair等于true時(shí),創(chuàng)建具有給定許可數(shù)的計(jì)數(shù)信號(hào)量并設(shè)置為公平信號(hào)量。
void acquire();//從此信號(hào)量獲取一個(gè)許可前線程將一直阻塞。相當(dāng)于一輛車占了一個(gè)車位。
void acquire(int n);//從此信號(hào)量獲取給定數(shù)目許可,在提供這些許可前一直將線程阻塞。比如n=2,就相當(dāng)于一輛車占了兩個(gè)車位。
void release();//釋放一個(gè)許可,將其返回給信號(hào)量。就如同車開走返回一個(gè)車位。
void release(int n);//釋放n個(gè)許可。
int availablePermits();//當(dāng)前可用的許可數(shù)。