java.util.concurrent包中有许多涉及多线程并发的工具,使用这些现成工具可以大大简化编码,并且安全高效。
Exchanger提供了一个同步点,即调用exchange方法,当两个线程都到达这个同步点时,两个线程交换数据。
比如,有两个人,一个人需要买一本书,另一个人当然卖一本书,这两个人约定在某地交易,但这两个人距离约定地不同,到达目的地的时间也不同,先到的必须等待直到另一个人到达完成交易。
使用Exchanger类可以很容易实现!
import java.util.*; import java.util.concurrent.*; interface Exchangable { } class Money implements Exchangable { private int value; public Money(int value) { this.value = value; } public String toString() { return "$" + value; } } class Book implements Exchangable { private int value; private String name; public Book(String name, int value) { this.name = name; this.value = value; } public String toString() { String format = "Book: %s($%d)"; return String.format(format, name, value); } } class Seller implements Runnable { Exchanger<Exchangable> exchanger; Exchangable book; public Seller(Exchanger<Exchangable> exchanger) { this.exchanger = exchanger; this.book = new Book("Love Java", 88); } public void run() { try { Random random = new Random(System.currentTimeMillis()); int seconds = random.nextInt(10) + 1; System.out.println("Hi, I am Seller, I am going to sell a book,waiting " + seconds + "s"); TimeUnit.SECONDS.sleep(seconds); System.out.println("Hi, I am Seller, I get " + exchanger.exchange(book)); } catch (Exception e) { } } } class Buyer implements Runnable { Exchanger<Exchangable> exchanger; Exchangable money; public Buyer(Exchanger<Exchangable> exchanger) { this.exchanger = exchanger; this.money = new Money(88); } public void run() { try { Random random = new Random(System.currentTimeMillis() + 99); int seconds = random.nextInt(10) + 1; System.out.println("Hi, I am Buyer, I am going to buy a book,waiting " + seconds + "s"); TimeUnit.SECONDS.sleep(seconds); System.out.println("Hi, I am Buyer, I get " + exchanger.exchange(money)); } catch (Exception e) { } } } public class ExchangerDemo { public static void main(String[] args) { Exchanger<Exchangable> exchanger = new Exchanger<>(); Seller seller = new Seller(exchanger); Buyer buyer = new Buyer(exchanger); new Thread(seller).start(); new Thread(buyer).start(); } }
Exchanger类使用很简单,只有两个public方法,一个是exchange(V x)方法,死等待直到完成交易,另一个是exchange(V x, long time, TimeUnit timeunit),其中x是要交换的数据,time是时间,timeunit指定时间单位,合起来表示最长等待时间,比如exchange(x, 5, TimeUnit.SECONDS)表示最长等待5秒!