返回介绍

9. 并发工具类 Exchanger

发布于 2024-09-08 13:17:47 字数 3333 浏览 0 评论 0 收藏 0

Exchanger,它允许在并发任务之间交换数据。具体来说,Exchanger 类允许在两个线程之间定义同步点。当两个线程都到达同步点时,他们交换数据结构,因此第一个线程的数据结构进入到第二个线程中,第二个线程的数据结构进入到第一个线程中。

应用示例

public class ExchangerTest {
    
     static class Producer implements Runnable{

        //生产者、消费者交换的数据结构
         private List<String> buffer;

        //生产者和消费者的交换对象
         private Exchanger<List<String>> exchanger;
         
         Producer(List<String> buffer,Exchanger<List<String>> exchanger){
             this.buffer=buffer;
             this.exchanger=exchanger;
         }
         
         
         
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                System.out.println("生产者第" +i +"次提供");
                for (int j = 0; j <=3; j++) {
                    System.out.println("生产者装入"+ i  +  "--" + j);
                    buffer.add("buffer :"+i +"--"+j);
                }
                System.out.println("生产者装满,等待与消费者交换....");
                
                try {
                    exchanger.exchange(buffer);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            
        }
         
     }
    
     static class Consumer implements Runnable{
         private List<String> buffer;
         private Exchanger<List<String>> exchanger;
         
         Consumer(List<String> buffer,Exchanger<List<String>> exchanger){
             this.buffer=buffer;
             this.exchanger=exchanger;
         }
         
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                //调用 exchange() 与消费者进行数据交换
                try {
                    buffer=exchanger.exchange(buffer);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("消费者第" + i + "次提取");
                for (int j = 0; j <=3; j++) {
                    System.out.println("消费者: "+buffer.get(0));
                    buffer.remove(0);
                }
            }    
            
        }
         
     }
    
     public static void main(String[] args) {
        List<String> buffer1=new ArrayList<String>();
        List<String> buffer2=new ArrayList<String>();
        Exchanger<List<String>> exchanger=new Exchanger<>();
        
        Thread t1=new Thread(new  Producer(buffer1, exchanger));
        Thread t2=new Thread(new  Consumer(buffer2, exchanger));
        t1.start();
        t2.start();
    }
}

  • 首先生产者 Producer、消费者 Consumer 首先都创建一个缓冲列表,通过 Exchanger 来同步交换数据。消费中通过调用 Exchanger 与生产者进行同步来获取数据,而生产者则通过 for 循环向缓存队列存储数据并使用 exchanger 对象消费者同步。到消费者从 exchanger 哪里得到数据后,他的缓冲列表中有 3 个数据,而生产者得到的则是一个空的列表。上面的例子充分展示了消费者-生产者是如何利用 Exchanger 来完成数据交换的。

在 Exchanger 中,如果一个线程已经到达了 exchanger 节点时,对于它的伙伴节点的情况有三种:

  1. 如果它的伙伴节点在该线程到达之前已经调用了 exchanger 方法,则它会唤醒它的伙伴然后进行数据交换,得到各自数据返回。

  2. 如果它的伙伴节点还没有到达交换点,则该线程将会被挂起,等待它的伙伴节点到达被唤醒,完成数据交换。

  3. 如果当前线程被中断了则抛出异常,或者等待超时了,则抛出超时异常。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文