簡單介紹AQS、ReetrantLock、CountDownLatch、CyclicBarrier、Semaphore

AQS,既AbstractQueuedSynchronizer, 是JUC包實現同步的基礎工具,是一個抽象類。

在AQS中,定義了一個volatile int state變量作爲共享資源,並且內置自旋鎖實現的同步隊列,封裝入隊和出隊的操作,提供獨佔、共享、中斷等特性的方法。

如果線程獲取資源失敗,則進入同步FIFO(先進先出)隊列中等待(入隊);
如果成功獲取資源就執行臨界區代碼。
執行完釋放資源時,通知隊列中的等待線程來獲取資源,然後出隊。

AQS的子類可以定義不停的資源實現不同性質的方法

ReetrantLock

可重入鎖。定義state爲0時可以獲取資源並置爲1.若已獲得資源,state不斷地+1,在釋放資源時state-1,直至爲0

CountDownLatch

CountDownLatch也是juc包中的一個類,類似倒計時計數器,初始時定義了資源總量state=count,調用await()方法則處於等待狀態。countDown()不斷地將state-1,當state=0時才能獲得鎖,所有線程都不會等待。

使用場景:
將主線程阻塞,等異步的多線程全部執行完畢並返回結果後,再繼續執行主線程。

public static List<String> getExecutorService() throws InterruptedException{
		System.out.println("開始執行多線程...");
		long startTime = System.currentTimeMillis();
		List<String> list = new CopyOnWriteArrayList<>();//存放返回結果
		CountDownLatch countDownLatch = new CountDownLatch(10);
		ExecutorService executorService = Executors.newFixedThreadPool(10);
		for (int i = 0; i < 10; i++) {
			Runnable runnable = new Runnable(){
 
				@Override
				public void run() {
					 try {
						Thread.sleep(3000);
                        list.add(UUID.randomUUID().toString());
                        System.out.println("當前線程name : "+Thread.currentThread().getName());
                        countDownLatch.countDown();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
			};
			executorService.execute(runnable);
		}
		countDownLatch.await();
		System.out.println("submit總共cost 時間:" + (System.currentTimeMillis()-startTime)/1000 + "秒");
		executorService.shutdown();
		return list;
	}

CountDownLatch是一次性的,state減到0後就釋放鎖,如果再想用就只能重新創建一個,如果希望循環使用,推薦使用CyclicBarrier.

Semaphore

信號量。與CountDownLatch不同的是,同樣也是定義了資源總量state=permits,當state>0時就能獲得鎖,並將state-1,當state=0時只能等待其他線程釋放鎖,當其他線程釋放鎖時state+1,這樣等待的線程又能獲得這個鎖

當Semaphore的permits定義爲1時,就是互斥鎖,當permits>1時就是共享鎖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章