后端开发进阶之路Java学习笔记技术干货

Java 中的 Exchanger 线程同步使用方法

2017-08-23  本文已影响77人  程序之心

Exchanger 类表示一种会合点,两个线程可以在这里交换对象。两个线程各自调用 exchange 方法进行交换,当线程 A 调用 Exchange 对象的 exchange 方法后,它会陷入阻塞状态,直到线程B也调用了 exchange 方法,然后以线程安全的方式交换数据,之后线程A和B继续运行。

exchange 方法有两个重载实现,在交换数据的时候还可以设置超时时间。如果一个线程在超时时间内没有其他线程与之交换数据,就会抛出 TimeoutException 超时异常。如果没有设置超时时间,则会一直等待。

//交换数据,并设置超时时间
public V exchange(V x, long timeout, TimeUnit unit) 
    throws InterruptedException, TimeoutException
//交换数据
public V exchange(V x) throws InterruptedException

如下的示例演示了 Exchanger 的使用方法。交换数据的类型是 String 字符串,两个线程的创建时间相差 5s,exchange 的超时时间是 100s,线程启动后打印初始字符串和交换后的字符串。

public class ExchangerTest {
    private Exchanger<String> exchanger = new Exchanger<>();
    
    public void test() throws Exception{
        testRunner("hello");
        Thread.sleep(5000);
        testRunner("world");
    }
    
    private void println(String msg){
        SimpleDateFormat sdf = new SimpleDateFormat("[YYYY-MM-dd HH:mm:ss:SSS] ");
        System.out.println(sdf.format(new Date()) + msg);
    }
    
    public void testRunner(String data){
        new Thread(() -> {
            try {
                println(Thread.currentThread().getName() + " receive " +data);
                // String newData = exchanger.exchange(data);
                String newData = exchanger.exchange(data,100,TimeUnit.SECONDS);
                println(Thread.currentThread().getName() + " has " +newData);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

执行结果如下,Thread-0 初始字符串为 hello,Thread-1 初始字符串为 world,Thread-0 等待交换数据等待了 5s,交换数据后 Thread-0 持有的字符串为 world,Thread-1 持有的字符串为 hello。

[2017-08-20 14:53:18:021] Thread-0 receive hello
[2017-08-20 14:53:23:003] Thread-1 receive world
[2017-08-20 14:53:23:003] Thread-1 has hello
[2017-08-20 14:53:23:003] Thread-0 has world

分享学习笔记和技术总结,内容涉及 Java 进阶、虚拟机、MySQL、NoSQL、分布式计算、开源框架等多个领域,欢迎关注作者。

image.png
上一篇下一篇

猜你喜欢

热点阅读