`
747017186
  • 浏览: 331372 次
社区版块
存档分类
最新评论

java线程之Exchanger

 
阅读更多

Exchanger的工作原理及实例

1.实现原理        

          Exchanger(交换者)是一个用于线程间协作的工具类。Exchanger用于进行线程间的数据交换。它提供一个同步点,在这个同步点两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据, 如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。因此使用Exchanger的重点是成对的线程使用exchange()方法,当有一对线程达到了同步点,就会进行交换数据。因此该工具类的线程对象是成对的

       Exchanger类提供了两个方法,String exchange(V x):用于交换,启动交换并等待另一个线程调用exchange;String exchange(V x,long timeout,TimeUnit unit):用于交换,启动交换并等待另一个线程调用exchange,并且设置最大等待时间,当等待时间超过timeout便停止等待。

2.实例讲解

        通过以上的原理,可以知道使用Exchanger类的核心便是exchange()方法的使用,接下来通过一个例子来使的该工具类的用途更加清晰。该例子主要讲解的是前段时间NBA交易截止日的交易。

  1.  
    package concurrent;
  2.  
    import java.util.concurrent.Exchanger;
  3.  
    import java.util.concurrent.ExecutorService;
  4.  
    import java.util.concurrent.Executors;
  5.  
    import java.util.*;
  6.  
    public class ExchangerDemo {
  7.  
     
  8.  
    public static void main(String[] args) {
  9.  
    ExecutorService executor = Executors.newCachedThreadPool();
  10.  
     
  11.  
    final Exchanger exchanger = new Exchanger();
  12.  
    executor.execute(new Runnable() {
  13.  
    String data1 = "克拉克森,小拉里南斯";
  14.  
     
  15.  
     
  16.  
    @Override
  17.  
    public void run() {
  18.  
    nbaTrade(data1, exchanger);
  19.  
    }
  20.  
    });
  21.  
     
  22.  
     
  23.  
    executor.execute(new Runnable() {
  24.  
    String data1 = "格里芬";
  25.  
     
  26.  
    @Override
  27.  
    public void run() {
  28.  
    nbaTrade(data1, exchanger);
  29.  
    }
  30.  
    });
  31.  
     
  32.  
    executor.execute(new Runnable() {
  33.  
    String data1 = "哈里斯";
  34.  
     
  35.  
    @Override
  36.  
    public void run() {
  37.  
    nbaTrade(data1, exchanger);
  38.  
    }
  39.  
    });
  40.  
     
  41.  
    executor.execute(new Runnable() {
  42.  
    String data1 = "以赛亚托马斯,弗莱";
  43.  
     
  44.  
    @Override
  45.  
    public void run() {
  46.  
    nbaTrade(data1, exchanger);
  47.  
    }
  48.  
    });
  49.  
     
  50.  
    executor.shutdown();
  51.  
    }
  52.  
     
  53.  
    private static void nbaTrade(String data1, Exchanger exchanger) {
  54.  
    try {
  55.  
    System.out.println(Thread.currentThread().getName() + "在交易截止之前把 " + data1 + " 交易出去");
  56.  
    Thread.sleep((long) (Math.random() * 1000));
  57.  
     
  58.  
    String data2 = (String) exchanger.exchange(data1);
  59.  
    System.out.println(Thread.currentThread().getName() + "交易得到" + data2);
  60.  
    } catch (InterruptedException e) {
  61.  
    e.printStackTrace();
  62.  
    }
  63.  
    }
  64.  
    }

运行程序,得到如下结果:

  1.  
    pool-1-thread-1在交易截止之前把 克拉克森,小拉里南斯 交易出去
  2.  
    pool-1-thread-2在交易截止之前把 格里芬 交易出去
  3.  
    pool-1-thread-3在交易截止之前把 哈里斯 交易出去
  4.  
    pool-1-thread-4在交易截止之前把 以赛亚托马斯,弗莱 交易出去
  5.  
    pool-1-thread-2交易得到哈里斯
  6.  
    pool-1-thread-3交易得到格里芬
  7.  
    pool-1-thread-4交易得到克拉克森,小拉里南斯
  8.  
    pool-1-thread-1交易得到以赛亚托马斯,弗莱

        以上例子可以看出两个都调用exchange()方法的线程会进行交换数据。接下来假设线程数目只有奇数个,观察情况:

如以下代码,将第四个线程注释掉。

  1.  
    package concurrent;
  2.  
    import java.util.concurrent.Exchanger;
  3.  
    import java.util.concurrent.ExecutorService;
  4.  
    import java.util.concurrent.Executors;
  5.  
    import java.util.*;
  6.  
    public class ExchangerDemo {
  7.  
     
  8.  
    public static void main(String[] args) {
  9.  
    ExecutorService executor = Executors.newCachedThreadPool();
  10.  
     
  11.  
    final Exchanger exchanger = new Exchanger();
  12.  
    executor.execute(new Runnable() {
  13.  
    String data1 = "克拉克森,小拉里南斯";
  14.  
     
  15.  
     
  16.  
    @Override
  17.  
    public void run() {
  18.  
    nbaTrade(data1, exchanger);
  19.  
    }
  20.  
    });
  21.  
     
  22.  
     
  23.  
    executor.execute(new Runnable() {
  24.  
    String data1 = "格里芬";
  25.  
     
  26.  
    @Override
  27.  
    public void run() {
  28.  
    nbaTrade(data1, exchanger);
  29.  
    }
  30.  
    });
  31.  
     
  32.  
    executor.execute(new Runnable() {
  33.  
    String data1 = "哈里斯";
  34.  
     
  35.  
    @Override
  36.  
    public void run() {
  37.  
    nbaTrade(data1, exchanger);
  38.  
    }
  39.  
    });
  40.  
     
  41.  
    // executor.execute(new Runnable() {
  42.  
    // String data1 = "以赛亚托马斯,弗莱";
  43.  
    //
  44.  
    // @Override
  45.  
    // public void run() {
  46.  
    // nbaTrade(data1, exchanger);
  47.  
    // }
  48.  
    // });
  49.  
     
  50.  
    executor.shutdown();
  51.  
    }
  52.  
     
  53.  
    private static void nbaTrade(String data1, Exchanger exchanger) {
  54.  
    try {
  55.  
    System.out.println(Thread.currentThread().getName() + "在交易截止之前把 " + data1 + " 交易出去");
  56.  
    Thread.sleep((long) (Math.random() * 1000));
  57.  
     
  58.  
    String data2 = (String) exchanger.exchange(data1);
  59.  
    System.out.println(Thread.currentThread().getName() + "交易得到" + data2);
  60.  
    } catch (InterruptedException e) {
  61.  
    e.printStackTrace();
  62.  
    }
  63.  
    }
  64.  
    }

运行程序,得到如下结果:

  1.  
    pool-1-thread-1在交易截止之前把 克拉克森,小拉里南斯 交易出去
  2.  
    pool-1-thread-2在交易截止之前把 格里芬 交易出去
  3.  
    pool-1-thread-3在交易截止之前把 哈里斯 交易出去
  4.  
    pool-1-thread-3交易得到格里芬
  5.  
    pool-1-thread-2交易得到哈里斯

        由结果可知,线程2和线程3进行了交换数据,而线程1一直等待与它交换数据的线程调用exchange,但是只有3个线程,所以会一直等待。

        因此,当两个线程之间出现数据交换的情况,可以使用Exchanger工具类实现数据交换。注意exchange方法的含义,以及触发数据交换的条件。

 

下面看代码例子:

package thread.exchanger;

import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExchangerTest {
	public static void main(String[] args) {
		ExecutorService pool = Executors.newCachedThreadPool();//线程缓存池
		final Exchanger<String> exchanger = new Exchanger<String>();//用于一对线程的交换
		
		pool.execute(new Runnable() {
			@Override
			public void run() {
				try {
					Thread.sleep((long)(Math.random()*10000));
					String data1 = "白粉";
					System.out.println("线程"+Thread.currentThread().getName()+"已经到达交换地点,准备拿"+data1+"交换!");
					data1 = exchanger.exchange(data1);//进行交换返回交换后的物品
					System.out.println("线程"+Thread.currentThread().getName()+"交换成功,拿到"+data1);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
		
		pool.execute(new Runnable() {
			@Override
			public void run() {
				try {
					Thread.sleep((long)(Math.random()*10000));
					String data2 = "钱";
					System.out.println("线程"+Thread.currentThread().getName()+"已经到达交换地点,准备拿"+data2+"交换!");
					data2 = exchanger.exchange(data2);//进行交换返回交换后的物品
					System.out.println("线程"+Thread.currentThread().getName()+"交换成功,拿到"+data2);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
		
		pool.shutdown();
	}
}



  

注意:exchanger只能用于一对或者一组线程的交换。交换的线程不能为奇数,否则会出现死锁等待。

 

 

 

 

  • 大小: 7.5 KB
分享到:
评论

相关推荐

    java线程与并发编程实践

    Java线程与并发编程实践是Java开发者必备的技能之一,特别是在多核处理器和高并发应用环境中,有效地管理和利用线程能极大地提升程序的性能。本书《java线程与并发实践编程》由Jeff Friesen撰写,2017年2月出版,...

    JAVA线程高级-线程按序交替执行

    在Java编程中,多线程是并发编程的重要组成部分,它允许程序同时执行多个任务,从而提高了系统的效率和响应性。然而,在某些场景下,我们可能需要控制线程的执行顺序,确保它们按照特定的顺序交替运行,这在并发编程...

    Java编程线程同步工具Exchanger的使用实例解析

    Java编程线程同步工具Exchanger的使用实例解析 Java编程线程同步工具Exchanger是Java编程语言中的一种线程同步工具,它提供了一种方便的方式来交换线程之间的信息。Exchanger类可以作为两个线程交换对象的同步点,...

    Java线程.zip

    Java线程是Java编程中的核心概念,它允许程序并发执行多个任务,提高系统资源的利用率,从而提升程序的效率和响应速度。Java线程的管理、同步和通信是每个Java开发者必须掌握的关键技能。 在Java中,线程的创建主要...

    Java多线程编程之使用Exchanger数据交换实例

    Java多线程编程中的Exchanger是一个非常有用的工具类,它位于`java.util.concurrent`包下,主要用于线程间的数据交换。Exchanger的核心功能是让两个线程在一个同步点相遇,进行数据交换。当一个线程调用`exchange`...

    java线程

    在深入探讨Java线程之前,我们首先需理解何为线程。线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以有多个线程,但至少有一个线程。在Java中,多线程编程是一...

    张孝祥Java多线程与并发库高级应用笔记

    Java线程技术是软件工程领域不可或缺的一部分,尤其在底层编程、Android应用开发以及游戏开发中,其重要性不言而喻。然而,尽管Java程序员普遍了解线程的基础概念,但在项目实践中,尤其是在复杂场景下处理多线程...

    Java:Exchanger类的作用.docx

    Java中的`Exchanger`类是`java.util.concurrent`包的一部分,设计用于在多线程环境中进行数据交换。这个类提供了一个同步点,使得两个线程能够有效地传递它们各自的数据。`Exchanger`的核心功能在于它维护了两个槽位...

    经典Java多线程与并发库高级应用

    Java线程是Java程序的基础,它代表程序中的一条执行线索或线路。在Java中创建线程有两种传统方式,一种是通过继承Thread类并覆盖其run方法来创建线程;另一种是通过传递实现了Runnable接口的对象给Thread类的构造...

    java并发Exchanger的使用

    Exchanger是java 5引入的并发类,Exchanger顾名思义就是用来做交换的。这里主要是两个线程之间交换持有的对象。当Exchanger在一个线程中调用exchange方法之后,会等待另外的线程调用同样的exchange方法。 两个线程都...

    JAVA集合、多线程

    4. **并发工具类**:java.util.concurrent包提供了多种并发工具,如Semaphore(信号量)、CountDownLatch(计数器)、CyclicBarrier(回环栅栏)和Exchanger(交换器),它们为多线程编程提供了更高级别的抽象和控制...

    深入了解java多线程

    Java线程的生命周期主要包括以下五个阶段: - **新建(New)**:当使用`Thread`类的构造函数创建一个新的线程对象时,线程处于新建状态。 - **就绪(Runnable)**:调用线程的`start()`方法后,线程进入就绪状态,...

    深入解析Java多线程

    最后,我们还需要了解Java并发工具类,如Semaphore(信号量)、CountDownLatch(计数器)、CyclicBarrier(回环栅栏)和Exchanger(交换器),它们为多线程编程提供了强大的支持。 总结来说,Java多线程涉及的内容...

    java线程入门

    此外,Java 还提供了其他并发工具类,如 CountDownLatch、CyclicBarrier、Semaphore 和 Exchanger,它们在多线程编程中有着广泛的应用。 在实际开发中,合理地使用线程和并发控制可以提高系统的并发性能,但同时也...

    多线程笔记_java/多线程_

    Java提供了一些高级同步工具,如Semaphore(信号量)、CyclicBarrier(循环屏障)、CountDownLatch(倒计时锁)和Exchanger(交换器),它们提供了更灵活的线程同步方式。 四、线程池 Java的ExecutorService和...

    java多线程设计模式(pdf)

    4. **并发工具类**:Java并发包(java.util.concurrent)提供了丰富的工具类,如Semaphore(信号量)、CountDownLatch(倒计时器)、CyclicBarrier(回环屏障)和Exchanger(交换器)等。这些工具可以用来协调线程间的行为,...

    Java多线程、并发编程知识点总结.pdf

    4. **线程状态**:Java线程具有多种状态,例如NEW(新建)、RUNNABLE(可运行)、BLOCKED(阻塞)、WAITING(等待)、TIMED_WAITING(定时等待)和TERMINATED(终止)。 5. **同步机制**:在多线程编程中,同步是...

    面向Java多线程机制的软件重构方法.pdf

    4. 线程状态:Java线程有五种状态,包括新建、就绪、运行、阻塞和终止。 二、并发与同步 1. 并发:多个线程在同一时间片内交替执行,宏观上看似同时运行。 2. 同步:控制多个线程对共享资源的访问,避免数据不...

    java多线程

    Java多线程是Java编程中一个非常重要的概念,它允许程序同时执行多个任务,从而提高系统资源的利用率和程序的响应速度。在网络编程中,多线程技术的应用尤为广泛,可以处理并发请求、异步数据传输等复杂场景。在这个...

    java并发工具类(CountDownLatch+Semaphore+Exchanger)

    Java并发工具类是Java并发编程中的重要组成部分,其中包括了多种实用的工具,如CountDownLatch、Semaphore和Exchanger,这些工具类极大地简化了多线程环境下的同步和协调问题。 1. **CountDownLatch**: ...

Global site tag (gtag.js) - Google Analytics