线程间的数据交换
如果要在两个线程间同步数据,使用Java并发API提供了的
Exchanger类会很方便。
Exchanger类允许在并发任务之间交换数据,它允许在两个线程之间定义同步点,当两个线程都达到同步点时进行数据交换:第一个线程的数据结构进入到第二个线程,第二个线程的数据结构进入到第一个线程。
本文用
Exchanger来解决一对一的生产者-消费者问题,示例代码如下:
public class ExchangerDemo {
public static void main(String[] args){
Exchanger<List<String>> exchanger = new Exchanger<List<String>>();
System.out.println("main;创建生产者和消费线程");
Thread t1 = new Thread(new ExchangerProducer(exchanger));
Thread t2 = new Thread(new ExchangerCustomer(exchanger));
System.out.println("main;启动生产者和消费线程");
t1.start();
t2.start();
}
}
class ExchangerCustomer implements Runnable{
private Exchanger<List<String>> exchanger;
private List<String> buffer;
ExchangerCustomer(Exchanger<List<String>> exchanger) {
this.exchanger = exchanger;
buffer = new ArrayList<String>(10);
}
@Override
public void run() {
for(int i=0; i<3; i++){
System.out.println("消费者:第" + i + "次数据交换");
try {
buffer = exchanger.exchange(buffer);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("消费者:完成数据交换。来自生产者的数据个数:" + buffer.size());
for(int j=0; j<buffer.size();j++){
System.out.print(buffer.get(j)+",");
}
System.out.println();
System.out.println("消费者:清空消费者数据。");
buffer.clear();;
}
}
}
class ExchangerProducer implements Runnable{
private Exchanger<List<String>> exchanger;
private List<String> buffer;
ExchangerProducer(Exchanger<List<String>> exchanger) {
this.exchanger = exchanger;
buffer = new ArrayList<String>(10);
}
@Override
public void run() {
for(int i=0; i<3; i++){
System.out.println("生产者:第" + i + "次数据交换");
//准备10个交换数据
for(int j=0; j<10 ;j++){
String msg = "Data:" + (i*10+j);
buffer.add(msg);
}
System.out.println("生产者:进行数据交换");
try {
buffer = exchanger.exchange(buffer);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("生产者:完成数据交换。来自消费者的数据个数:" + buffer.size());
}
}
}
程序运行日志:
main;创建生产者和消费线程
main;启动生产者和消费线程
生产者:第0次数据交换
生产者:进行数据交换
消费者:第0次数据交换
生产者:完成数据交换。来自消费者的数据个数:0
生产者:第1次数据交换
生产者:进行数据交换
消费者:完成数据交换。来自生产者的数据个数:10
Data:0,Data:1,Data:2,Data:3,Data:4,Data:5,Data:6,Data:7,Data:8,Data:9,
消费者:清空消费者数据。
消费者:第1次数据交换
消费者:完成数据交换。来自生产者的数据个数:10
生产者:完成数据交换。来自消费者的数据个数:0
Data:10,生产者:第2次数据交换
Data:11,Data:12,生产者:进行数据交换
Data:13,Data:14,Data:15,Data:16,Data:17,Data:18,Data:19,
消费者:清空消费者数据。
消费者:第2次数据交换
消费者:完成数据交换。来自生产者的数据个数:10
Data:20,Data:21,生产者:完成数据交换。来自消费者的数据个数:0
Data:22,Data:23,Data:24,Data:25,Data:26,Data:27,Data:28,Data:29,
消费者:清空消费者数据。