美文网首页Java基础总结
Java/Android Exchanger 必知必会

Java/Android Exchanger 必知必会

作者: Little丶Jerry | 来源:发表于2018-09-09 23:24 被阅读13次
    问:你知道 Java 的 Exchanger 吗?简单说说其特点及应用场景?

    答:Exchanger 是 JDK 1.5 开始提供的一个用于两个工作线程之间交换数据的封装工具类,简单说就是一个线程在完成一定的事务后想与另一个线程交换数据,则第一个先拿出数据的线程会一直等待第二个线程,直到第二个线程拿着数据到来时才能彼此交换对应数据。其定义为 Exchanger<V> 泛型类型,其中 V 表示可交换的数据类型,对外提供的接口很简单,具体如下:

    • Exchanger():无参构造方法。

    • V exchange(V v):等待另一个线程到达此交换点(除非当前线程被中断),然后将给定的对象传送给该线程,并接收该线程的对象。

    • V exchange(V v, long timeout, TimeUnit unit):等待另一个线程到达此交换点(除非当前线程被中断或超出了指定的等待时间),然后将给定的对象传送给该线程,并接收该线程的对象。

    可以看出,当一个线程到达 exchange 调用点时,如果其他线程此前已经调用了此方法,则其他线程会被调度唤醒并与之进行对象交换,然后各自返回;如果其他线程还没到达交换点,则当前线程会被挂起,直至其他线程到达才会完成交换并正常返回,或当当前线程被中断或超时返回。

    public class Test {
        static class Producer extends Thread {
            private Exchanger<Integer> exchanger;
            private static int data = 0;
            Producer(String name, Exchanger<Integer> exchanger) {
                super("Producer-" + name);
                this.exchanger = exchanger;
            }
    
            @Override
            public void run() {
                for (int i=1; i<5; i++) {
                    try {
                        TimeUnit.SECONDS.sleep(1);
                        data = i;
                        System.out.println(getName()+" 交换前:" + data);
                        data = exchanger.exchange(data);
                        System.out.println(getName()+" 交换后:" + data);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        static class Consumer extends Thread {
            private Exchanger<Integer> exchanger;
            private static int data = 0;
            Consumer(String name, Exchanger<Integer> exchanger) {
                super("Consumer-" + name);
                this.exchanger = exchanger;
            }
    
            @Override
            public void run() {
                while (true) {
                    data = 0;
                    System.out.println(getName()+" 交换前:" + data);
                    try {
                        TimeUnit.SECONDS.sleep(1);
                        data = exchanger.exchange(data);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(getName()+" 交换后:" + data);
                }
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            Exchanger<Integer> exchanger = new Exchanger<Integer>();
            new Producer("", exchanger).start();
            new Consumer("", exchanger).start();
            TimeUnit.SECONDS.sleep(7);
            System.exit(-1);
        }
    }
    

    可以看到,其结果可能如下:

    Consumer- 交换前:0
    Producer- 交换前:1
    Consumer- 交换后:1
    Consumer- 交换前:0
    Producer- 交换后:0
    Producer- 交换前:2
    Producer- 交换后:0
    Consumer- 交换后:2
    Consumer- 交换前:0
    Producer- 交换前:3
    Producer- 交换后:0
    Consumer- 交换后:3
    Consumer- 交换前:0
    Producer- 交换前:4
    Producer- 交换后:0
    Consumer- 交换后:4
    Consumer- 交换前:0
    

    可以看到,如上就是一种典型的使用场景,简单理解这东西就是一个并发协作的工具类而已。

    本文参考自 Java/Android Exchanger 必知必会实战题分析

    相关文章

      网友评论

        本文标题:Java/Android Exchanger 必知必会

        本文链接:https://www.haomeiwen.com/subject/pnqjgftx.html