java juc exchanger_JUC之Exchanger
JUC中的Exchanger允许成对的线程在指定的同步点上通过exchange方法来交换数据。如果第一个线程先执行exchange方法,它会一直等待第二个线程也 执行exchange方法,当两个线程都到达同步点时,这两个线程就可以交换数据,将当前线程生产 出来的数据传递给对方。
Exchanger示例
两个线程通过Exchanger交换数据的简单示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27public class ExchangerTest{
public static void main(String[] args){
final Exchanger exchanger = new Exchanger<>();
new Thread(() -> {
System.out.println("thread1开始");
try {
String exchange = exchanger.exchange("来自thread1的数据");
System.out.println("接收thread2发送的数据:" + exchange);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread1结束");
}, "thread1").start();
new Thread(() -> {
System.out.println("thread2开始");
try {
String exchange = exchanger.exchange("来自thread2的数据");
System.out.println("接收thread1发送的数据:" + exchange);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread2结束");
}, "thread2").start();
}
}
在定义Exchanger的时候需要指定交换的数据类型,这里为String类型。exchange方法用于向另一个线程发送数据,方法的返回值为另一个线程发送过来的数据。上面例子输出如下:1
2
3
4
5
6thread1开始
thread2开始
接收thread2发送的数据:来自thread2的数据
thread1结束
接收thread1发送的数据:来自thread1的数据
thread2结束
上面说过,只有当成对的线程都到达同步点的时候,才会执行数据交换操作。现在我们让thread2休眠一会儿,看看thread1是否会进入等待:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28public class ExchangerTest{
public static void main(String[] args){
final Exchanger exchanger = new Exchanger<>();
new Thread(() -> {
System.out.println("thread1开始");
try {
String exchange = exchanger.exchange("来自thread1的数据");
System.out.println("接收thread2发送的数据:" + exchange);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread1结束");
}, "thread1").start();
new Thread(() -> {
System.out.println("thread2开始");
try {
TimeUnit.SECONDS.sleep(3); // thread1也会进入等待,直到双方都准备好交换数据。
String exchange = exchanger.exchange("来自thread2的数据");
System.out.println("接收thread1发送的数据:" + exchange);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread2结束");
}, "thread2").start();
}
}
程序输出如下所示:
那么如果线程不成对会出现什么情况呢?我们添加thread3线程:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38public class ExchangerTest{
public static void main(String[] args){
final Exchanger exchanger = new Exchanger<>();
new Thread(() -> {
System.out.println("thread1开始");
try {
String exchange = exchanger.exchange("发送数据-thread1");
System.out.println("接收数据:" + exchange);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread1结束");
}, "thread1").start();
new Thread(() -> {
System.out.println("thread2开始");
try {
String exchange = exchanger.exchange("发送数据-thread2");
System.out.println("接收数据:" + exchange);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread2结束");
}, "thread2").start();
new Thread(() -> {
System.out.println("thread3开始");
try {
String exchange = exchanger.exchange("发送数据-thread3");
System.out.println("接收数据:" + exchange);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread3结束");
}, "thread3").start();
}
}
程序输出如下所示:1
2
3
4
5
6
7thread1开始
thread3开始
接收数据:发送数据-thread1
thread3结束
thread2开始
接收数据:发送数据-thread3
thread1结束
可看到thread1和thread3交换了数据然后正常停止了,而thread2由于没有线程和它交换数据而苦苦等待,线程永远不会停止。查看线程快照可以证明这点:
线程匹配是随机的,所以也有可能thread1和thread2匹配,thread3进入无休止的等待,这就类似于…
另一个值得一提的点就是通过Exchanger交换的是同一个对象,而不是对象的拷贝:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31public class ExchangerTest{
public static void main(String[] args){
final Exchanger exchanger = new Exchanger<>();
new Thread(() -> {
System.out.println("thread1开始");
Object object = new Object();
System.out.println("thread1发送数据:" + object);
try {
Object exchange = exchanger.exchange(object);
System.out.println("接收thread2发送的数据:" + exchange);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread1结束");
}, "thread1").start();
new Thread(() -> {
System.out.println("thread2开始");
Object object = new Object();
System.out.println("thread2发送数据:" + object);
try {
Object exchange = exchanger.exchange(object);
System.out.println("接收thread1发送的数据:" + exchange);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread2结束");
}, "thread2").start();
}
}
程序输出如下:1
2
3
4
5
6
7
8thread1开始
thread2开始
thread2发送数据:java.lang.Object@6d559005
thread1发送数据:java.lang.Object@7702c19
接收thread2发送的数据:java.lang.Object@6d559005
接收thread1发送的数据:java.lang.Object@7702c19
thread2结束
thread1结束
可以看到thread1发送的对象和thread2接收的对象句柄是一致的。
设置超时时间
如果不想线程在交换数据的时候等待过长的时间,我们可以使用exchanger的重载方法exchange(V x, long timeout, TimeUnit unit)来指定超时时间:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28public class ExchangerTest{
public static void main(String[] args){
final Exchanger exchanger = new Exchanger<>();
new Thread(() -> {
System.out.println("thread1开始");
try {
String exchange = exchanger.exchange("来自thread1的数据", 5, TimeUnit.SECONDS);
System.out.println("接收thread2发送的数据:" + exchange);
} catch (InterruptedException | TimeoutException e) {
e.printStackTrace();
}
System.out.println("thread1结束");
}, "thread1").start();
new Thread(() -> {
System.out.println("thread2开始");
try {
TimeUnit.SECONDS.sleep(10);
String exchange = exchanger.exchange("来自thread2的数据");
System.out.println("接收thread1发送的数据:" + exchange);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread2结束");
}, "thread2").start();
}
}
上面例子中,thread2休眠10秒后才开始交换数据,而thread1在等待5秒后没能成功交换数据就抛出TimeoutException异常了。10秒后由于没有线程再和thread2交换数据,所以thread2会一直等待:
java juc exchanger_JUC之Exchanger相关推荐
- java juc exchanger_JUC——Exchanger
A synchronization point at which threads can pair and swap elements within pairs. Each thread presen ...
- Java JUC工具类--Exchanger
Exchanger Exchanger用于进行线程间的数据交换,它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据 两个线程通过exchange方法交换数据,如果一个线程先执行exchange ...
- java juc exchanger_JUC工具类实例
描述 本文描述了JUC中CountDownLatch.CyclicBarrier.Semaphore.Exchanger工具类使用方式. CountDownLatch 以下代码为例:主线程阻塞直到Co ...
- Java JUC学习 - ConcurrentLinkedDeque 详解
Java JUC学习 - ConcurrentLinkedDeque 详解 0x00 前言 如何实现并发程序,对于Java以及其他高级语言来说都是一件并不容易的事情.在大一上学期的时候,我们学习了链表 ...
- Java JUC并发编程详解
Java JUC并发编程详解 1. JUC概述 1.1 JUC简介 1.2 进程与线程 1.2 并发与并行 1.3 用户线程和守护线程 2. Lock接口 2.1 Synchronized 2.2 什 ...
- Java JUC高并发编程(三)-CallableJUC辅助类
目录 一.Callable接口 二.JUC辅助类 1.减少计数CountDownLatch 2.循环栅栏CyclicBarrier 3.信号灯Semaphore 一.Callable接口 Callab ...
- Java juc系列6 —— 线程池
Java JUC系列目录链接 Java 线程池核心原理解析 Java线程池的基础用法 创建和使用 为什么需要线程池 线程的生命周期[^1] 新建 就绪 运行 休眠 终止 使用线程的代价 线程池帮我们做 ...
- Java JUC系列
1.Java JUC 简介 2.volatile 关键字-内存可见性 3.原子变量 CAS算法 4.ConcurrentHashMap 锁分段机制 5.CountDownLatch 闭锁 6.实现 C ...
- Java JUC高并发编程(一)
目录 一.概述 二.Lock接口 三.线程间的通信 解决虚假唤醒问题 Lock通信示例: 四.线程间定制化通信 一.概述 JUC就是java.util.concurrent工具包的简称,这是一个处理线 ...
最新文章
- h265player开发
- 祝大家春节快乐身体健康
- 本地环境的搭配及安装配置
- C#编程中的crc16校验
- python 路由转发_RabbitMQ之路由键转发消息
- 【机器学习基础】数学推导+纯Python实现机器学习算法18:奇异值分解SVD
- mysql数据库入门第二张试卷_2016计算机二级《MySQL数据库》练习题与答案
- OScached页面缓存的入门使用
- ABAP Development Tools的语法高亮实现原理
- 简化 Pod 故障诊断:kubectl-debug 介绍
- Nuget如何自动下载依赖DLL引用
- 这个韩国女星在节目里吃了“巨型蛤蜊” 可能要坐牢5年了...
- Objective-C的算术表达式
- Could not resolve type alias ‘‘
- python多PDF文件合成一个
- myline java线段类,MyLine 编写一个线段类 MyLine 联合开发网 - pudn.com
- linux 查看IP地址
- 详解 python 的 切片
- 自然语言处理是什么,我们为什么需要处理自然语言?
- managed-schema配置文件详解