java.util.concurrent包(7)——Exchanger使用

简介:
Java 并发 API 提供了一种允许2个并发任务间相互交换数据的同步应用。更具体的说,Exchanger类允许在2个线程间定义同步点,当2个线程到达这个点,他们相互交换数据类型,使用第一个线程的数据类型变成第二个的,然后第二个线程的数据类型变成第一个的。

示例1
一个人有零食,另一个人有钱,他们两个想等价交换,对好口号在某个地方相见,一个人先到了之后,必须等另一个人带着需要的东西来了之后,才能开始交换。
public class ExchangerTest
{
public static void main(String[] args)
{
ExecutorService service = Executors.newCachedThreadPool();
final Exchanger<String> exchanger = new Exchanger<String>();
service.execute(new Runnable()
{
public void run()
{
try
{
String data1 = "零食";
System.out.println("线程" + Thread.currentThread().getName() + "正在把数据" + data1 + "换出去");
Thread.sleep((long) (Math.random() * 1000));
String data2 = exchanger.exchange(data1);
System.out.println("线程" + Thread.currentThread().getName() + "换回的数据为" + data2);
}
catch (Exception e)
{
}
}
});

service.execute(new Runnable()
{
public void run()
{
try
{
String data1 = "钱";
System.out.println("线程" + Thread.currentThread().getName() + "正在把数据" + data1 + "换出去");
Thread.sleep((long) (Math.random() * 1000));
String data2 = exchanger.exchange(data1);
System.out.println("线程" + Thread.currentThread().getName() + "换回的数据为" + data2);
}
catch (Exception e)
{
}
}
});
}
}
线程pool-1-thread-1正在把数据零食换出去
线程pool-1-thread-2正在把数据钱换出去
线程pool-1-thread-2换回的数据为零食
线程pool-1-thread-1换回的数据为钱


示例2
这个类在遇到类似生产者和消费者问题时,是非常有用的。来一个非常经典的并发问题:你有相同的数据buffer,一个或多个数据生产者,和一个或多个数据消费者。只是Exchange类只能同步2个线程,所以你只能在你的生产者和消费者问题中只有一个生产者和一个消费者时使用这个类。
public class Producer implements Runnable
{

// 要被相互交换的数据类型。
private List<String> buffer;

// 用来同步 producer和consumer
private final Exchanger<List<String>> exchanger;

public Producer(List<String> buffer, Exchanger<List<String>> exchanger)
{
this.buffer = buffer;
this.exchanger = exchanger;
}

public void run()
{
// 实现10次交换
for (int i = 0; i < 10; i++)
{
buffer.add("第" + i + "次生产者的数据" + i);
try
{
// 调用exchange方法来与consumer交换数据
System.out.println("第" + i + "次生产者在等待.....");
buffer = exchanger.exchange(buffer);
System.out.println("第" + i + "次生产者交换后的数据:" + buffer.get(i));
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}


public class Consumer implements Runnable
{

// 用来相互交换
private List<String> buffer;

// 用来同步 producer和consumer
private final Exchanger<List<String>> exchanger;

public Consumer(List<String> buffer, Exchanger<List<String>> exchanger)
{
this.buffer = buffer;
this.exchanger = exchanger;
}

public void run()
{
// 实现10次交换
for (int i = 0; i < 10; i++)
{
buffer.add("第" + i + "次消费者的数据" + i);
try
{
// 调用exchange方法来与consumer交换数据
System.out.println("第" + i + "次消费者在等待.....");
buffer = exchanger.exchange(buffer);
System.out.println("第" + i + "次消费者交换后的数据:" + buffer.get(i));
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}

public class Core
{
public static void main(String[] args)
{
// 创建2个buffers,分别给producer和consumer使用
List<String> buffer1 = new ArrayList<String>();
List<String> buffer2 = new ArrayList<String>();

// 创建Exchanger对象,用来同步producer和consumer
Exchanger<List<String>> exchanger = new Exchanger<List<String>>();

// 创建Producer对象和Consumer对象
Producer producer = new Producer(buffer1, exchanger);
Consumer consumer = new Consumer(buffer2, exchanger);

// 创建线程来执行producer和consumer并开始线程
Thread threadProducer = new Thread(producer);
Thread threadConsumer = new Thread(consumer);
threadProducer.start();
threadConsumer.start();
}
}
Exchanger 类有另外一个版本的exchange方法
exchange(V data, long time, TimeUnit unit)
V是声明参数种类,例子中是List
此线程会休眠直到另一个线程到达并中断它,或者特定的时间过去了
TimeUnit类有多种常量,DAYS、HOURS、MICROSECONDS、MILLISECONDS、MINUTES、NANOSECONDS和SECONDS

原帖地址:
http://blog.csdn.net/howlaa/article/details/19853447
http://ifeve.com/thread-synchronization-utilities-8/
目录
相关文章
|
27天前
|
Java Docker 容器
|
2月前
|
Java 数据安全/隐私保护
JAVA包
JAVA包
13 0
|
3月前
|
安全 Java API
Java并发基础:Exchanger全面解析!
Exchanger类的优点在于能够简洁高效地实现两个线程间的数据交换,通过Exchanger,开发者可以避免复杂的锁和同步机制,降低并发编程的难度,同时,它还提供了线程安全的数据交换保障,使得多线程协作更为可靠、易用性和高效性。
Java并发基础:Exchanger全面解析!
|
5月前
|
存储 Java 编译器
Java编程中,包声明(Package Declaration)
Java编程中,包声明(Package Declaration)
85 1
|
5月前
|
Java 关系型数据库 Linux
Linux|Java|jar包的解压和重新打包(更新配置)
Linux|Java|jar包的解压和重新打包(更新配置)
82 0
|
8天前
|
Java 测试技术 数据安全/隐私保护
滚雪球学Java(23):包机制
【4月更文挑战第12天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
25 3
滚雪球学Java(23):包机制
|
24天前
|
Java Maven
【Java报错】显示错误“Error:java: 程序包org.springframework.boot不存在“
【Java报错】显示错误“Error:java: 程序包org.springframework.boot不存在“
37 3
|
4月前
|
分布式计算 Java 大数据
IO流【Java对象的序列化和反序列化、File类在IO中的作用、装饰器模式构建IO流体系、Apache commons-io工具包的使用】(四)-全面详解(学习总结---从入门到深化)
IO流【Java对象的序列化和反序列化、File类在IO中的作用、装饰器模式构建IO流体系、Apache commons-io工具包的使用】(四)-全面详解(学习总结---从入门到深化)
53 0
|
3天前
|
存储 Java
Java的`java.io`包包含多种输入输出类
Java的`java.io`包包含多种输入输出类。此示例展示如何使用`FileInputStream`从`input.txt`读取数据。首先创建`FileInputStream`对象,接着分配一个`byte`数组存储流中的数据。通过`read()`方法读取数据,然后将字节数组转换为字符串打印。最后关闭输入流释放资源。`InputStream`是抽象类,此处使用其子类`FileInputStream`。其他子类如`ByteArrayInputStream`、`ObjectInputStream`和`BufferedInputStream`各有特定用途。
11 1
|
3天前
|
Java
如何解决使用若依前后端分离打包部署到服务器上后主包无法找到从包中的文件的问题?如何在 Java 代码中访问 jar 包中的资源文件?
如何解决使用若依前后端分离打包部署到服务器上后主包无法找到从包中的文件的问题?如何在 Java 代码中访问 jar 包中的资源文件?
12 0