1.CyclicBarrier(屏障)
CyclicBarrier类是通过设置屏障点来管理同步的,当所有参与的线程都到达指定屏障的时候,那么参与的所有线程就会全部 积蓄运行,具体测试代码如下:
public class CyclicBarrierTest { // 定义一个循环屏障 private CyclicBarrier cyclicBarrier; // 构造函数 //count为参与执行的线程数 //rn为所有线程到达屏障后需要做的行为 public CyclicBarrierTest(int count, Runnable rn) { this.cyclicBarrier = new CyclicBarrier(count, rn); } public void sayHello(String name, int time) { System.out.println("开始执行:" + name); try { Thread.sleep(time); this.cyclicBarrier.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println("结束执行:" + name); } public static void main(String[] args) { final CyclicBarrierTest cbt = new CyclicBarrierTest(3, new Runnable() { @Override public void run() { System.out.println("执行数量的线程完成后执行"); } }); // 创建三个测试线程 Thread t1 = new Thread(new Runnable() { @Override public void run() { cbt.sayHello("T1", 500); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { cbt.sayHello("T2", 1000); } }); Thread t3 = new Thread(new Runnable() { @Override public void run() { cbt.sayHello("T3", 2000); } }); //启动三个线程 t1.start(); t2.start(); t3.start(); } }
上述代码的运行结果,应该是:
开始执行:T1
开始执行:T2
开始执行:T3
执行数量的线程完成后执行
结束执行:T1
结束执行:T2
结束执行:T3
2.CountDownLatch(计数)
CountDownLatch类是通过线程计数来实现同步的,也就是有一个计数器,在计数器未到0之前所有相关线程在指定位置都需要阻 塞,直到计数器为0的时候,所有相关线程停止阻塞,继续向下执行。需要注意的是,该同步器不能被复用,并且可以由外部事件触发。
public class CountDownLatchTest { private CountDownLatch countDownLatch = null; //构造函数,创建倒计时同步器 //count为倒计时数 public CountDownLatchTest(int count){ this.countDownLatch = new CountDownLatch(count); } //递减计数器 public void countDown(){ this.countDownLatch.countDown(); System.out.println("count:" + this.countDownLatch.getCount()); } public void sayHello(String name, int time) { System.out.println("开始执行:" + name); try { Thread.sleep(time); this.countDownLatch.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("结束执行:" + name); } public static void main(String[] args) throws InterruptedException { final CountDownLatchTest cdl = new CountDownLatchTest(3); // 创建三个测试线程 Thread t1 = new Thread(new Runnable() { @Override public void run() { cdl.sayHello("T1", 50); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { cdl.sayHello("T2", 50); } }); Thread t3 = new Thread(new Runnable() { @Override public void run() { cdl.sayHello("T3", 50); } }); //启动测试线程 t1.start(); t2.start(); t3.start(); Thread.sleep(2000); //逐步递减 cdl.countDown(); Thread.sleep(1000); cdl.countDown(); Thread.sleep(1000); cdl.countDown(); Thread.sleep(1000); } }
上述代码由于线程运行的不确定性,每次的运行结果都不一样,但原则不变,例如:
开始执行:T1
开始执行:T2
开始执行:T3
count:2
count:1
count:0
结束执行:T2
结束执行:T3
结束执行:T1
3.Exchanger(交换)
Exchanger类用于不同线程间交换数据,并且交换过程是线程安全的,通过设置一个同步点来实现,具体代码如下:
public class ExchangerTest { private Exchanger<String> exchanger; public ExchangerTest(){ this.exchanger = new Exchanger<String>(); } public void method1(String name){ System.out.println("执行Mehtod1"); //Thread.sleep(1000);\ String ss = name + "发送数据:123123" ; try { ss = this.exchanger.exchange(ss); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("结束Mehtod1"); } public void method2(String name){ System.out.println("执行Mehtod2"); String ss = "123"; try { ss = this.exchanger.exchange(ss); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Mehotd2收到:" + ss); System.out.println("结束Mehtod2"); } public static void main(String[] args) { final ExchangerTest et = new ExchangerTest(); // 创建三个测试线程 Thread t1 = new Thread(new Runnable() { @Override public void run() { et.method1("T1"); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { et.method2("T2"); } }); //启动测试线程 t2.start(); t1.start(); } }
上述代码的运行结果,应该是:
执行Mehtod2
执行Mehtod1
结束Mehtod1
Mehotd2收到:T1发送数据:123123
结束Mehtod2
4.SynchronousQueue(同步队列)
该同步器是阻塞队列的一种,虽然称之为队列,但是该“队列”没有长度。使用该队列的规则是:没有存不允许取,没有取不允许存。该队列的方法很多,但一般使用较多的是put和take方法,因为这两个方法实现了阻塞方式的存取,代码如下:
public class SynchronousQueueTest { private SynchronousQueue<String> synchronousQueue; public SynchronousQueueTest(){ //构造函数内的参数表示是否采取公平策略 //即优先照顾等待时间比较长的线程 //使用公平策略会影响性能 this.synchronousQueue = new SynchronousQueue<String>(false); } public void put(String data){ try { System.out.println("等待放入:" + data); this.synchronousQueue.put(data); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public String take(){ String data = null; try { data = this.synchronousQueue.take(); System.out.println("提取了:" + data); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return data; } public static void main(String[] args) { final SynchronousQueueTest sqt = new SynchronousQueueTest(); // 创建三个测试线程 Thread t1 = new Thread(new Runnable() { @Override public void run() { sqt.put("111111"); try { Thread.sleep(4000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } sqt.put("222222"); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { sqt.take(); sqt.take(); } }); //启动测试线程 t1.start(); t2.start(); } }
上述代码的运行结果,应该是:
等待放入:111111
提取了:111111
等待放入:222222
提取了:222222
5.Semaphore(信号量)
Semaphore类通过类似许可证的方式对同步进行管理,简单的来说,许可证的数目是一定的,想要访问,必须要获得许可证,若许可证已经用完,那么必须等待其他占用许可证的线程归还许可证后,方可得到许可从而继续执行。具体代码如下:
public class SemaphoreTest { private Semaphore semaphore; //构造函数用于创建一个信号量同步器 //count为许可个数 //fair表示是否采用公平策略 public SemaphoreTest(int count,boolean fair){ this.semaphore = new Semaphore(count,fair); } public void sayHello(String name){ try { this.semaphore.acquire(); System.out.println(name + "得到许可"); Thread.sleep(5000); this.semaphore.release(); System.out.println(name + "释放许可"); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { final SemaphoreTest st = new SemaphoreTest(3,false); // 创建测试线程 Thread t1 = new Thread(new Runnable() { @Override public void run() { st.sayHello("T1"); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { st.sayHello("T2"); } }); Thread t3 = new Thread(new Runnable() { @Override public void run() { st.sayHello("T3"); } }); Thread t4 = new Thread(new Runnable() { @Override public void run() { st.sayHello("T4"); } }); Thread t5 = new Thread(new Runnable() { @Override public void run() { st.sayHello("T5"); } }); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); } }
上述代码由于线程运行的不确定性,每次的运行结果都不一样,但原则不变,例如:
T1得到许可
T2得到许可
T4得到许可
T2释放许可
T4释放许可
T3得到许可
T1释放许可
T5得到许可
T3释放许可
T5释放许可
相关推荐
详细的讲述了多线程的各种用法 Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 ...Java线程:新特征-障碍器 Java线程:大总结
Java分布式应用学习笔记05多线程下的并发同步器
Java 线程系列博文总结word化,编目如下,欢迎互相学习交流: Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 ...Java线程:新特征-障碍器
Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 ...Java线程:新特征-障碍器 Java线程:大总结
Java线程:概念与原理 Java线程:创建与启动 ...Java线程:新特征-障碍器 Java线程:深入ThreadLocal 一、标准例子 二、不用ThreadLocal 三、自己实现个ThreadLocal 四、透过现象看本质 Java线程:大总结
Java多线程机制 9.1 Java中的线程 9.2 Thread的子类创建线程 ...9.6 线程同步 9.7 在同步方法中使用wait()、notify 和notifyAll()方法 9.8 挂起、恢复和终止线程 9.9 计时器线程Timer 9.10 线程联合 9.11 守护线程
包含java线程的概念、原理、交互、合并、让步、守护、休眠、同步、锁以及新特性 锁 线程池 信号量 有返回值的线程 原子量 障碍器 阻塞列队和阻塞栈。java开发必备参考文档。
主要介绍了Java多线程同步器代码详解,文章分别介绍了是CountDownLatch,Semaphore,Barrier和Exchanger以及其相关代码示例,具有一定参考价值,需要的朋友可以了解下。
lettuce - 高级Java Redis客户端,用于线程安全同步,异步和reactive用法。 支持群集,Sentinel,管道和编解码器。
包括java的Thread类,同步块(synchronized),可重入锁,Object方法以及对象监视器等内容。
java分布式应用学习笔记05多线程下的并发同步器.pdf
java并非编程,合集(各种锁、并发集合、障碍器、线程同步)
线程同步Synchronized,监视器monitor和锁lock的关系2---马克-to-win java视频
线程同步Synchronized,监视器monitor和锁lock的关系1---马克-to-win java视频
线程同步Synchronized,监视器monitor和锁lock的关系2---马克-to-win java视频
主要介绍了java多线程编程同步器Future和FutureTask解析及代码示例,对二者进行了详细介绍,分析了future的源码,最后展示了相关实例代码,具有一定参考价值 ,需要的朋友可以了解下。
莴苣是一个可扩展的线程安全redis客户端,用于同步,
在下载过程中处理线程同步和资源释放,确保线程安全性和资源的正确释放。 异常处理:在实现过程中需要考虑各种异常情况,如网络连接异常、文件IO异常等,需要进行适当的异常处理和错误提示,保证程序的稳定性和可靠...