闭锁、栅栏、交换机、信号量学习笔记
来源:互联网 发布:发散和收敛定义知乎 编辑:程序博客网 时间:2024/05/26 02:21
1.闭锁(CountDownLatch)
通过一个计数器实现,原理就是不停地检查join线程是否存活,如果存活则一直等待,作用是m(m>=1)个线程等待其他的线程执行玩之后然后继续往下执行,类似join()方法,但功能更强大,可以操作更多的线程。
public class TestTemp { public static void main(String[] args) throws InterruptedException { CountDownLatch latch = new CountDownLatch(3);//计数器初始值设置为3 Waiter waiter = new Waiter(latch); Decrementer decrementer = new Decrementer(latch); new Thread(waiter) .start(); new Thread(decrementer).start(); Thread.sleep(4000); }} class Waiter implements Runnable{ CountDownLatch latch = null; public Waiter(CountDownLatch latch) { this.latch = latch; } public void run() { try { latch.await();//阻塞在这边 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Waiter Released"); }}class Decrementer implements Runnable { CountDownLatch latch = null; public Decrementer(CountDownLatch latch) { this.latch = latch;} public void run() { try { Thread.sleep(1000); this.latch.countDown();//计数器减1 Thread.sleep(1000); this.latch.countDown();//计数器减1 Thread.sleep(1000); this.latch.countDown();//计数器减1 } catch (InterruptedException e) { e.printStackTrace(); } }}当计数器的值减少为0的时候,Waiter线程就能够不再阻塞,继续往下运行了。
2.栅栏
使用场景:所有线程相互等待,直到所有线程都到达某一点时才打开栅栏,然后线程继续执行。
public class TestTemp { public static void main(String[] args) throws InterruptedException { Runnable barrier1Action = new Runnable() { public void run() { System.out.println("BarrierAction 1 executed "); } }; Runnable barrier2Action = new Runnable() { public void run() { System.out.println("BarrierAction 2 executed "); } }; CyclicBarrier barrier1 = new CyclicBarrier(2, barrier1Action);//有两个线程等待就执行barrier1Action CyclicBarrier barrier2 = new CyclicBarrier(2, barrier2Action);//有两个线程等待就执行barrier2Action CyclicBarrierRunnable barrierRunnable1 = new CyclicBarrierRunnable(barrier1, barrier2); CyclicBarrierRunnable barrierRunnable2 = new CyclicBarrierRunnable(barrier1, barrier2); new Thread(barrierRunnable1).start(); new Thread(barrierRunnable2).start(); }} class CyclicBarrierRunnable implements Runnable{ CyclicBarrier barrier1 = null; CyclicBarrier barrier2 = null; public CyclicBarrierRunnable(CyclicBarrier barrier1, CyclicBarrier barrier2) { this.barrier1 = barrier1; this.barrier2 = barrier2; } public void run() { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() +" waiting at barrier 1"); this.barrier1.await();//等在这里呢 Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + " waiting at barrier 2"); this.barrier2.await(); System.out.println(Thread.currentThread().getName() + " done!"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }}可以看到触发的条件仅仅和两个线程本身有关,而闭锁和外部的条件(计数器)来触发,它们的触发条件是不同的。
3.交换机
使用场景:用户线程之间的数据交互,替代wait和notify
public class TestTemp { public static void main(String[] args) throws InterruptedException { Exchanger exchanger = new Exchanger(); ExchangerRunnable exchangerRunnable1 = new ExchangerRunnable(exchanger, "A"); ExchangerRunnable exchangerRunnable2 = new ExchangerRunnable(exchanger, "B"); new Thread(exchangerRunnable1).start(); new Thread(exchangerRunnable2).start(); }} class ExchangerRunnable implements Runnable{ Exchanger exchanger = null; Object object = null; public ExchangerRunnable(Exchanger exchanger, Object object) { this.exchanger = exchanger; this.object = object; } public void run() { try { Object previous = this.object; this.object = this.exchanger.exchange(this.object); System.out.println(Thread.currentThread().getName() + " exchanged " + previous + " for " + this.object ); } catch (InterruptedException e) { e.printStackTrace(); } }}
4.信号量
作用:
1. 保护一个重要(代码)部分防止一次超过 N 个线程进入。
2. 在两个线程之间发送信号。
public class TestTemp { public static void main(String[] args) throws InterruptedException { Service service = new Service(); ThreadA a = new ThreadA(service); a.setName("A"); ThreadB b = new ThreadB(service); b.setName("B"); ThreadC c = new ThreadC(service); c.setName("C"); a.start(); b.start(); c.start(); } }class Service { private Semaphore semaphore = new Semaphore(1);//同一个时刻,只有一个线程可以执行acquire和release部分的代码 public void testMethod() { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + " begin timer=" + System.currentTimeMillis()); Thread.sleep(5000); System.out.println(Thread.currentThread().getName() + " end timer=" + System.currentTimeMillis()); semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } }}class ThreadA extends Thread { private Service service; public ThreadA(Service service) { super(); this.service = service; } @Override public void run() { service.testMethod(); }}class ThreadB extends Thread { private Service service; public ThreadB(Service service) { super(); this.service = service; } @Override public void run() { service.testMethod(); }} class ThreadC extends Thread { private Service service; public ThreadC(Service service) { super(); this.service = service; } @Override public void run() { service.testMethod(); }}
阅读全文
0 0
- 闭锁、栅栏、交换机、信号量学习笔记
- 同步工具类闭锁,栅栏,信号量
- 闭锁/栅栏/信号量/FutureTask分析及使用
- 同步工具类--闭锁、信号量、栅栏的总结
- 同步工具类(闭锁,信号量,栅栏,FutureTask)
- 同步工具类--闭锁、信号量、栅栏的总结
- 捡拾日记:闭锁、栅栏
- 闭锁和栅栏
- 闭锁CountDownLatch与栅栏CyclicBarrier
- 闭锁CountDownLatch与栅栏CyclicBarrier
- 闭锁CountDownLatch和栅栏CyclicBarrier
- 闭锁CountDownLatch与栅栏CyclicBarrier
- 闭锁CountDownLatch与栅栏CyclicBarrier
- 闭锁CountDownLatch与栅栏CyclicBarrier
- Java并发学习笔记(三)-闭锁CountDownLatch
- JAVA栅栏和闭锁的区别
- AQS(6):闭锁和信号量
- 闭锁、同步屏障、信号量详解
- 欢迎使用CSDN-markdown编辑器
- Hadoop下用MapReduce处理WordCount
- python序列大作战之可变序列
- 工作笔记本的挑选方法与使用方法(笔记)
- Python4--if-else、while循环
- 闭锁、栅栏、交换机、信号量学习笔记
- PHP导出EXCEL
- BZOJ 1054
- 输入两个数求之间的平方数
- machine-learning-ex3
- 《组合数学引论》第二章部分习题解答
- 在macOS下R的xlsx安装
- BZOJ 3119 Book (贪心+数学推导)
- Oracle实用工具 sqlDeveloper使用之数据迁移