Java并发编程--6.Exchanger线程间交换数据

在两个线程之间定义同步点,当两个线程都到达同步点时,他们交换数据结构,因此第一个线程的数据结构进入到第二个线程中,第二个线程的数据结构进入到第一个线程中

在生产者-消费者情境模式中它包含了一个数缓冲区,一个或者多个生产者,一个或者多个消费中

下面是生产者和消费者的示例:

/**
 * 生产者和消费者交换数据
 */
public class MyExchanger {
    public static void main(String[] args) {
        Exchanger<List<String>> exchanger = new Exchanger<List<String>>();

        Producer1 producer = new Producer1(new ArrayList<String>(), exchanger);
        Consumer1 consumer = new Consumer1(new ArrayList<String>(), exchanger);

        new Thread(producer).start();
        new Thread(consumer).start();
    }
}

/** 生产者线程*/
 class Producer1 implements Runnable{

    /**
     * 存储交换的数据
     */
    private List<String> buffer;

    /**
     * 和消费者要交换的对象
     */
    private final Exchanger<List<String>> exchanger;

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

    @Override
    public void run() {
        for(int i = 0 ; i < 2 ; i++){
                String message = "" + i ;
                System.out.println("Produce的数据 : " + message);
                buffer.add(message);

            //调用exchange()与消费者进行数据交换
            try {
                buffer = exchanger.exchange(buffer);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println("Produce收到来自Consumer的数据的长度 : " + buffer.size());
    }
}

/** 消费者线程*/
class Consumer1 implements Runnable{
        private List<String> buffer;

        private final Exchanger<List<String>> exchanger;

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

        @Override
        public void run() {
            for(int i = 0 ; i < 2 ; i++){
                //调用exchange()与消费者进行数据交换
                try {
                    buffer = exchanger.exchange(buffer);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                for(int j = 0 ; j < buffer.size() ; j++){
                    System.out.println("Consumer收到来自Produce的数据 : " + buffer.get(0));
                    buffer.remove(0);
                }
            }

            System.out.println("Consumer清空数据");
        }
    }

控制台输出:

Produce的数据 : 0
Consumer收到来自Produce的数据 : 0
Produce的数据 : 1
Produce收到来自Consumer的数据的长度 : 0
Consumer收到来自Produce的数据 : 1
Consumer清空数据

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

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

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

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

时间: 2024-10-25 19:50:47

Java并发编程--6.Exchanger线程间交换数据的相关文章

JAVA 并发编程-多个线程之间共享数据(六)

多线程共享数据的方式: 1,如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,卖票系统就可以这么做. 2,如果每个线程执行的代码不同,这时候需要用不同的Runnable对象,例如,设计4个线程.其中两个线程每次对j增加1,另外两个线程对j每次减1,银行存取款 有两种方法来解决此类问题: 将共享数据封装成另外一个对象,然后将这个对象逐一传递给各个Runnable对象,每个线程对共享数据的操作方法也分配到那个对象身上完成,这样容易实现针对

Java并发工具类(四):线程间交换数据的Exchanger

简介 Exchanger(交换者)是一个用于线程间协作的工具类.Exchanger用于进行线程间的数据交换.它提供一个同步点,在这个同步点两个线程可以交换彼此的数据.这两个线程通过exchange方法交换数据, 如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方. Exchanger的应用场景 1.Exchanger可以用于遗传算法,遗传算法里需要选出两个人作为交配对象,这时

Java并发工具类(四)线程间交换数据的Exchanger

简介 Exchanger(交换者)是一个用于线程间协作的工具类.Exchanger用于进行线程间的数据交换.它提供一个同步点,在这个同步点两个线程可以交换彼此的数据.这两个线程通过exchange方法交换数据, 如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方. Exchanger的应用场景 1,Exchanger可以用于遗传算法,遗传算法里需要选出两个人作为交配对象,这时

Java并发工具类之线程间数据交换工具Exchanger

Exchanger是一个用于线程间协做的工具类,主要用于线程间的数据交换.它提供了一个同步点,在这个同步点,两个线程可以彼此交换数据.两个线程通过exchange方法交换数据,如果一个线程执行exchange方法,它就会等待另一个线程执行exchange方法,当两个线程都到达了同步点,这两个线程就可以交换数据.将本线程产生的数据传送给对方. Exchanger可用于工作的互相校对,比如我们要把线下产生的交易数据通过人工录入的方式添加到系统中,为了避免错误,我们采用AB两人同时录入的方式,当录入完

【java并发编程实战】-----线程基本概念

学习Java并发已经有一个多月了,感觉有些东西学习一会儿了就会忘记,做了一些笔记但是不系统,对于Java并发这么大的"系统",需要自己好好总结.整理才能征服它.希望同仁们一起来学习Java并发编程,共同进步,互相指导. 在学习Java并发之前我们需要先理解一些基本的概念:共享.可变.线程安全性.线程同步.原子性.可见性.有序性. 共享和可变 要编写线程安全的代码,其核心在于对共享的和可变的状态进行访问. "共享"就意味着变量可以被多个线程同时访问.我们知道系统中的资

Java并发编程系列(一)-线程的基本使用

最近在学习java并发编程基础.一切从简,以能理解概念为主. 并发编程肯定绕不过线程.这是最基础的. 那么就从在java中,如何使用线程开始. 继承Thread类 继承Thread类,重写run方法,new出对象,调用start方法. 在新启的线程里运行的就是重写的run方法. 1 /** 2 * 集成Thread类 实现run() 3 */ 4 public class C1 extends Thread { 5 6 @Override 7 public void run() { 8 try

Java并发编程学习:线程安全与锁优化

本文参考<深入理解java虚拟机第二版> 一.什么是线程安全? 这里我借<Java Concurrency In Practice>里面的话:当多个线程访问一个对象,如果不考虑这些线程在运行时环境下的调度和交替执行,也不需要额外的同步,或者调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那么这个对象是线程安全的. 我的理解:多线程访问一个对象,任何情况下,都能保持正确行为,就是对象就是安全的. 我们可以将Java语言中各种操作共享的数据分为以下5类:不可变.

Java并发编程(01):线程的创建方式,状态周期管理

本文源码:GitHub·点这里 || GitEE·点这里 一.并发编程简介 1.基础概念 程序 与计算机系统操作有关的计算机程序.规程.规则,以及可能有的文件.文档及数据. 进程 进程是计算机中的程序,关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体:在面向线程设计的计算机结构中,进程是线程的容器.程序是指令.数据及其组织形式的描述,进程是程序的实体. 线程 线程是操作系统能够进行运算调度的最小单

Java并发编程系列-(2) 线程的并发工具类

2.线程的并发工具类 2.1 Fork-Join JDK 7中引入了fork-join框架,专门来解决计算密集型的任务.可以将一个大任务,拆分成若干个小任务,如下图所示: Fork-Join框架利用了分而治之的思想:什么是分而治之?规模为N的问题,N<阈值,直接解决,N>阈值,将N分解为K个小规模子问题,子问题互相对立,与原问题形式相同,将子问题的解合并得到原问题的解. 具体使用中,需要向ForkJoinPool线程池提交一个ForkJoinTask任务.ForkJoinTask任务有两个重要