Java线程--Exchanger交换器

Exchanger交换器

目录

Exchanger交换器

Exchanger概念 

Exchanger示例 

Exchanger和Semaphore区别 

 借花献佛


Exchanger概念 

Java线程--Exchanger交换器_第1张图片

上图业务场景描述:A有球,想要和B的鱼交互,整个交互过程描述如下:

A在准备素材,球,准备的比较快,然后就发出交换诉求,exchange(球),发现B还没带着鱼来,就阻塞在这里。B这时还在钓鱼,等B钓到鱼后,立马发出交换诉求,exchange(鱼),发现A阻塞在那里了,就把A唤醒,然后两人互换了东西,A拥有了鱼,B拥有了球。

 

A synchronization point at which threads can pair and swap elements within pairs. Each thread presents some object on entry to the exchange method, matches with a partner thread, and receives its partner's object on return. An Exchanger may be viewed as a bidirectional form of a SynchronousQueue. Exchangers may be useful in applications such as genetic algorithms and pipeline designs.

    在以上的描述中,有几个要点:

  • 交换值是同步的
  • 成对的线程之间交换数据;
  • 可看成是双向的同步队列;
  • 可应用于演算法、流水线设计;

Exchanger类中的主要方法就是:exchange(V x)方法,成对的两个线程之间,都调用了该方法,就能在两个线程彼此都准备好数据后,成功的交换数据给对方,然后各自返回。如果想支持成对的两个线程之间,一个没耐性,等的时间过长,或者被打断了就不交换数据了,可以使用exchange(V x, long timeout, TimeUnit unit)方法。


Exchanger示例 

import java.util.concurrent.*;
import java.util.concurrent.locks.*;
import java.util.concurrent.atomic.*;

//球线程
class BallTask implements Runnable
{
    private Exchanger e;
    public BallTask(Exchanger e){
	this.e = e;
    }

    public void run(){
	try{
	    long sleepTime = (long)(Math.random() * 2500) ;
	    String tName = Thread.currentThread().getName();
	    System.out.println(tName+"正在买球,用时["+sleepTime+"]才买到球,赶紧去换鱼...");
	    Thread.sleep(sleepTime);
	    String str = e.exchange(tName+":的球");
	    System.out.println("【"+tName+":的球】换到了-->【"+str+"】");
	}
	catch(Exception e){
	}
	finally{
	}
    }
}


//鱼线程
class FishTask implements Runnable
{
    private Exchanger e;
    public FishTask(Exchanger e){
	this.e = e;
    }

    public void run(){
	try{
	    long sleepTime = (long)(Math.random() * 2500) ;
            String tName = Thread.currentThread().getName();
	    System.out.println(tName+"正在钓鱼,用时["+sleepTime+"]才钓到鱼,赶紧去换球...");
	    Thread.sleep(sleepTime);
	    String str = e.exchange(tName+":的鱼");
	    System.out.println("【"+tName+":的鱼】换到了-->【"+str+"】");
	}
	catch(Exception e){
	}
	finally{
	}
    }
}

public class ExchangerTest
{
    public static void main(String[] args) 
    {
	Exchanger e = new Exchanger();

	BallTask bTask = new BallTask(e);		//任务:球线程
	FishTask fTask = new FishTask(e);		//任务:鱼线程

	Thread bThread = new Thread(bTask,"Ball");
	Thread fThread = new Thread(fTask,"Fish");

	bThread.start();
	fThread.start();

	System.out.println("我是主线程,准备看看你们交易情况...\n\r");

	try{
	    bThread.join();
	    fThread.join();
	}catch(Exception ep){}

	System.out.println("\n\r我是主线程,已看到你们的交易结果...");
    }
}

程序运行结果如下:

我是主线程,准备看看你们交易情况...

Ball正在买球,用时[88]才买到球,赶紧去换鱼...
Fish正在钓鱼,用时[2215]才钓到鱼,赶紧去换球...

【Fish:的鱼】换到了-->【Ball:的球】
【Ball:的球】 换到了-->【Fish:的鱼】

我是主线程,已看到你们的交易结果...


Exchanger和Semaphore区别 

Exchanger交换器和Semaphore信号量在关于生产者消费者《产1消1模式》运用的区别:

  • Exchanger交换器:成对的两个线程,各个线程有各个线程的自己数据V,A线程拥有V1,B线程拥有V2,V1<...>V2互换。 
  • Semaphore信号量:成对的两个线程,只需一个数据池即可,生产者生产数据注入数据池,消费者从数据池取走数据消费。
  • Exchanger交换器:两个线程之间的通讯仅仅一个Exchanger实例即可。
  • Semaphore信号量:两个线程之间的通讯需要两个信号量,生产信号指示灯,消费信号指示灯。
  • Exchanger和Semaphore的共同点:两个线程之间需要同步通讯。生产的过快,没用,必须等消费完了,才能进行下一生产1;同理,消费的过快,也没用,必须等生产完了,才能进行下一消费1。

 借花献佛

摘自博客(http://brokendreams.iteye.com/blog/2253956)

其实就是”我”和”你”(可能有多个”我”,多个”你”)在一个叫Slot的地方做交易(一手交钱,一手交货),过程分以下步骤:

1。我先到一个叫做Slot的交易场所交易,发现你已经到了,那我就尝试喊你交易,如果你回应了我,决定和我交易那么进入第2步;如果别人抢先一步把你喊走了,那我就进入第5步。


2。我拿出钱交给你,你可能会接收我的钱,然后把货给我,交易结束;也可能嫌我掏钱太慢(超时)或者接个电话(中断),TM的不卖了,走了,那我只能再找别人买货了(从头开始)。


3。我到交易地点的时候,你不在,那我先尝试把这个交易点给占了(一屁股做凳子上…),如果我成功抢占了单间(交易点),那就坐这儿等着你拿货来交易,进入第4步;如果被别人抢座了,那我只能在找别的地方儿了,进入第5步。


4。你拿着货来了,喊我交易,然后完成交易;也可能我等了好长时间你都没来,我不等了,继续找别人交易去,走的时候我看了一眼,一共没多少人,弄了这么多单间(交易地点Slot),太TM浪费了,我喊来交易地点管理员:一共也没几个人,搞这么多单间儿干毛,给哥撤一个!。然后再找别人买货(从头开始);或者我老大给我打了个电话,不让我买货了(中断)。


5。我跑去喊管理员,尼玛,就一个坑交易个毛啊,然后管理在一个更加开阔的地方开辟了好多个单间,然后我就挨个来看每个单间是否有人。如果有人我就问他是否可以交易,如果回应了我,那我就进入第2步。如果我没有人,那我就占着这个单间等其他人来交易,进入第4步。 


6。如果我尝试了几次都没有成功,我就会认为,是不是我TM选的这个单间风水不好?不行,得换个地儿继续(从头开始);如果我尝试了多次发现还没有成功,怒了,把管理员喊来:给哥再开一个单间(Slot),加一个凳子,这么多人就这么几个破凳子够谁用!

 

 

 

你可能感兴趣的:(Java,Thread,Java,Thread,线程)