山東專業(yè)網站解決方案制作石家莊抖音seo
文章目錄
- 學習鏈接
- CountDownLatch
- CountDownLatch類的作用
- 類的主要方法介紹
- 圖解await和countDown方法
- 兩個典型用法
- 注意點
- 總結
- 示例
- CountDownLatchDemo1
- CountDownLatchDemo2
- CountDownLatchDemo1And2
- CyclicBarrier
- CyclicBarrier循環(huán)柵欄
- CyclicBarrier和CountDownLatch的區(qū)別
- 示例
- CyclicBarrierDemo
- Semaphore
- Semaphore信號量
- Semaphore應用實例
- 信號量的使用流程
- 信號量主要方法介紹
- 信號量的特殊用法
- 注意點
- 示例
- SemaphoreDemo
- Condition
- Condition的作用
- signalAll和signal的區(qū)別
- Condition注意點
- 示例
- Condition1
- Condition2
學習鏈接
Java并發(fā)編程第9講——CountDownLatch、CyclicBarrier和Semaphore(萬字詳解)
CountDownLatch
CountDownLatch類的作用
類的主要方法介紹
圖解await和countDown方法
兩個典型用法
注意點
總結
示例
CountDownLatchDemo1
/*** 描述:工廠中,質檢,5個工人檢查,所有人都認為通過,才通過*/
public class CountDownLatchDemo1 {public static void main(String[] args) throws InterruptedException {CountDownLatch latch = new CountDownLatch(5);ExecutorService service = Executors.newFixedThreadPool(5);for (int i = 0; i < 5; i++) {final int no = i + 1;Runnable runnable = new Runnable() {@Overridepublic void run() {try {Thread.sleep((long) (Math.random() * 10000));System.out.println("No." + no + "完成了檢查。");} catch (InterruptedException e) {e.printStackTrace();} finally {latch.countDown();}}};service.submit(runnable);}System.out.println("等待5個人檢查完.....");latch.await(); // 這里也可以設置超時等待時間, 如: latch.await(5, TimeUnit.SECONDS);System.out.println("所有人都完成了工作,進入下一個環(huán)節(jié)。");}
}
CountDownLatchDemo2
/*** 描述:模擬100米跑步,5名選手都準備好了,只等裁判員一聲令下,所有人同時開始跑步。*/
public class CountDownLatchDemo2 {public static void main(String[] args) throws InterruptedException {CountDownLatch begin = new CountDownLatch(1);ExecutorService service = Executors.newFixedThreadPool(5);for (int i = 0; i < 5; i++) {final int no = i + 1;Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println("No." + no + "準備完畢,等待發(fā)令槍");try {begin.await();System.out.println("No." + no + "開始跑步了");} catch (InterruptedException e) {e.printStackTrace();}}};service.submit(runnable);}//裁判員檢查發(fā)令槍...Thread.sleep(5000);System.out.println("發(fā)令槍響,比賽開始!");begin.countDown();}
}
CountDownLatchDemo1And2
/*** 描述:模擬100米跑步,5名選手都準備好了,只等裁判員一聲令下,所有人同時開始跑步。當所有人都到終點后,比賽結束。*/
public class CountDownLatchDemo1And2 {public static void main(String[] args) throws InterruptedException {CountDownLatch begin = new CountDownLatch(1);CountDownLatch end = new CountDownLatch(5);ExecutorService service = Executors.newFixedThreadPool(5);for (int i = 0; i < 5; i++) {final int no = i + 1;Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println("No." + no + "準備完畢,等待發(fā)令槍");try {begin.await();System.out.println("No." + no + "開始跑步了");Thread.sleep((long) (Math.random() * 10000));System.out.println("No." + no + "跑到終點了");} catch (InterruptedException e) {e.printStackTrace();} finally {end.countDown();}}};service.submit(runnable);}//裁判員檢查發(fā)令槍...Thread.sleep(5000);System.out.println("發(fā)令槍響,比賽開始!");begin.countDown();end.await();System.out.println("所有人到達終點,比賽結束");}
}
CyclicBarrier
CyclicBarrier循環(huán)柵欄
CyclicBarrier和CountDownLatch的區(qū)別
示例
CyclicBarrierDemo
/*** 描述: 演示CyclicBarrier*/
public class CyclicBarrierDemo {public static void main(String[] args) {// 5個線程都調用await時,才執(zhí)行Runnable,然后5個線程接著執(zhí)行CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() {@Overridepublic void run() {System.out.println("所有人都到場了, 大家統(tǒng)一出發(fā)!");}});// 這里循環(huán)10次,目的是驗證CyclicBarrier可重用for (int i = 0; i < 10; i++) {new Thread(new Task(i, cyclicBarrier)).start();}}static class Task implements Runnable {private int id;private CyclicBarrier cyclicBarrier;public Task(int id, CyclicBarrier cyclicBarrier) {this.id = id;this.cyclicBarrier = cyclicBarrier;}@Overridepublic void run() {System.out.println("線程" + id + "現(xiàn)在前往集合地點");try {Thread.sleep((long) (Math.random() * 10000));System.out.println("線程" + id + "到了集合地點,開始等待其他人到達");cyclicBarrier.await();System.out.println("線程" + id + "出發(fā)了");} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}}
}
Semaphore
Semaphore信號量
Semaphore應用實例
信號量的使用流程
信號量主要方法介紹
信號量的特殊用法
注意點
示例
SemaphoreDemo
/*** 描述: 演示Semaphore用法*/
public class SemaphoreDemo {static Semaphore semaphore = new Semaphore(3, true);public static void main(String[] args) {ExecutorService service = Executors.newFixedThreadPool(50);for (int i = 0; i < 100; i++) {service.submit(new Task());}service.shutdown();}static class Task implements Runnable {@Overridepublic void run() {try {semaphore.acquire(1);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "拿到了許可證");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "釋放了許可證");semaphore.release(1);}}
}
Condition
Condition的作用
signalAll和signal的區(qū)別
Condition注意點
示例
Condition1
/*** 描述:演示Condition的基本用法*/
public class ConditionDemo1 {private ReentrantLock lock = new ReentrantLock();private Condition condition = lock.newCondition();void method1() throws InterruptedException {lock.lock();try{System.out.println("條件不滿足,開始await");condition.await(); // 可設置超時時間進入條件等待: condition.await(1, TimeUnit.SECONDS);System.out.println("條件滿足了,開始執(zhí)行后續(xù)的任務");}finally {lock.unlock();}}void method2() {lock.lock();try{System.out.println("準備工作完成,喚醒其他的線程");condition.signal();}finally {lock.unlock();}}public static void main(String[] args) throws InterruptedException {ConditionDemo1 conditionDemo1 = new ConditionDemo1();new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(1000);conditionDemo1.method2();} catch (InterruptedException e) {e.printStackTrace();}}}).start();conditionDemo1.method1();}
}
Condition2
/*** 描述: 演示用Condition實現(xiàn)生產者消費者模式*/
public class ConditionDemo2 {private int queueSize = 10;private PriorityQueue<Integer> queue = new PriorityQueue<Integer>(queueSize);private Lock lock = new ReentrantLock();// 當隊列不滿足 不滿的條件時,生產者進入等待// (當隊列不滿時,喚醒在此條件中等待的線程)private Condition notFull = lock.newCondition();// 當隊列不滿足 不空的條件時,消費者進入等待// (當隊列不空時,喚醒在此條件中等待的線程)private Condition notEmpty = lock.newCondition();public static void main(String[] args) {ConditionDemo2 conditionDemo2 = new ConditionDemo2();Producer producer = conditionDemo2.new Producer();Consumer consumer = conditionDemo2.new Consumer();producer.start();consumer.start();}class Consumer extends Thread {@Overridepublic void run() {consume();}private void consume() {while (true) {lock.lock();try {// 使用while, 防止了虛假喚醒while (queue.size() == 0) {System.out.println("隊列空,等待數(shù)據(jù)");try {// 當隊列為空時,進入等待// 當隊列不為空時,被喚醒notEmpty.await(); // 進入條件隊列中等待,并釋放鎖;此處被喚醒時,仍然需要獲取到鎖,才能往下運行} catch (InterruptedException e) {e.printStackTrace();}}// 走到這里說明隊列肯定不為空了// (因為先持有了鎖, 所以保證了操作的原子性。其它此時嘗試從該隊列中獲取數(shù)據(jù)的線程將進入鎖等待環(huán)節(jié))queue.poll();// 因為拿到了鎖, 并且從隊列中獲取了數(shù)據(jù), 隊列此時肯定不為滿了, 所以可以喚醒生產者線程去生產notFull.signalAll();System.out.println("從隊列里取走了一個數(shù)據(jù),隊列剩余" + queue.size() + "個元素");} finally {lock.unlock();}}}}class Producer extends Thread {@Overridepublic void run() {produce();}private void produce() {while (true) {lock.lock();try {// 使用while, 防止了虛假喚醒while (queue.size() == queueSize) {System.out.println("隊列滿,等待有空余");try {// 當隊列為滿時,進入等待// 當隊列為不滿時,被喚醒notFull.await(); // 進入條件隊列中等待,并釋放鎖;此處被喚醒時,仍然需要獲取到鎖,才能往下運行} catch (InterruptedException e) {e.printStackTrace();}}// 走到這里說明隊列肯定不為滿了// (因為先持有了鎖, 所以保證了操作的原子性。其它此時嘗試往該隊列中添加數(shù)據(jù)的線程將進入鎖等待環(huán)節(jié))queue.offer(1);// 因為拿到了鎖, 并且往該隊列中添加了數(shù)據(jù), 隊列此時肯定不為空了, 所以可以喚醒消費者者線程去消費notEmpty.signalAll();System.out.println("向隊列插入了一個元素,隊列剩余空間" + (queueSize - queue.size()));} finally {lock.unlock();}}}}}