/** * @Description: *讓一些線程阻塞直到另外一些線程完成一系列操做後才被喚醒。 * <p> * CountDownLatch主要有兩個方法,當一個或多個線程調用await方法時,這些線程會阻塞。 * 其它線程調用countDown方法會將計數器減1(調用countDown方法的線程不會阻塞), * 當計數器的值變爲0時,因await方法阻塞的線程會被喚醒,繼續執行。 * <p> * 解釋:6個同窗陸續離開教室後值班同窗才能夠關門。 * <p> * main主線程必需要等前面6個線程完成所有工做後,本身才能開幹 */ public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(6); for (int i = 1; i <= 6; i++) //6個上自習的同窗,各自離開教室的時間不一致 { new Thread(() -> { System.out.println(Thread.currentThread().getName() + "\t 號同窗離開教室"); countDownLatch.countDown(); }, String.valueOf(i)).start(); } countDownLatch.await(); System.out.println(Thread.currentThread().getName() + "\t****** 班長關門走人,main線程是班長"); } }
/** * CyclicBarrier * 的字面意思是可循環(Cyclic)使用的屏障(Barrier)。它要作的事情是, * 讓一組線程到達一個屏障(也能夠叫同步點)時被阻塞, * 直到最後一個線程到達屏障時,屏障纔會開門,全部 * 被屏障攔截的線程纔會繼續幹活。 * 線程進入屏障經過CyclicBarrier的await()方法。 * <p> * 集齊7顆龍珠就能夠召喚神龍 */ public class CyclicBarrierDemo { public static void main(String[] args) { //CyclicBarrier(int parties, Runnable barrierAction) CyclicBarrier cyclicBarrier = new CyclicBarrier( 7, () -> { System.out.println("*****集齊7顆龍珠就能夠召喚神龍"); }); for (int i = 1; i <= 7; i++) { new Thread(() -> { try { System.out.println(Thread.currentThread().getName() + "\t 星龍珠被收集 "); cyclicBarrier.await(); } catch (InterruptedException | BrokenBarrierException e) { // TODO Auto-generated catch block e.printStackTrace(); } }, String.valueOf(i)).start(); } } }
忽然又想到一個知識點(跑題中。。)wait 、await、sleep、notify、signal的區別:
wait----sleepnode
public final void await() throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); Node node = addConditionWaiter(); int savedState = fullyRelease(node); int interruptMode = 0; while (!isOnSyncQueue(node)) { LockSupport.park(this); if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) break; } if (acquireQueued(node, savedState) && interruptMode != THROW_IE) interruptMode = REINTERRUPT; if (node.nextWaiter != null) // clean up if cancelled unlinkCancelledWaiters(); if (interruptMode != 0) reportInterruptAfterWait(interruptMode); }
先說下來源,await是ConditionObject類裏面的方法,ConditionObject實現了Condition接口;而ReentrantLock裏面默認有實現newCondition()方法,新建一個條件對象。該方法就是用在ReentrantLock中根據條件來設置等待。喚醒方法也是由專門的Signal()或者Signal()來執行。另外await會致使當前線程被阻塞,會放棄鎖,這點和wait是同樣的。併發
因爲所在的超類不一樣使用場景也不一樣,wait通常用於Synchronized中,而await只能用於ReentrantLock鎖中.
notify----signal
notify使用來喚醒使用wait的線程;而signal是用來喚醒await線程。dom
/**ui
@Description: TODO(這裏用一句話描述這個類的做用)this
在信號量上咱們定義兩種操做:線程
acquire(獲取) 當一個線程調用acquire操做時,它要麼經過成功獲取信號量(信號量減1),code
要麼一直等下去,直到有線程釋放信號量,或超時。對象
release(釋放)實際上會將信號量的值加1,而後喚醒等待的線程。接口
信號量主要用於兩個目的,一個是用於多個共享資源的互斥使用,另外一個用於併發線程數的控制。
*/
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);//模擬3個停車位ip
for (int i = 1; i <= 6; i++) //模擬6部汽車 { new Thread(() -> { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + "\t 搶到了車位"); TimeUnit.SECONDS.sleep(new Random().nextInt(5)); System.out.println(Thread.currentThread().getName() + "\t ----離開了車位"); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); } }, String.valueOf(i)).start(); }
} }