程序笔记   发布时间:2022-07-18  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了多线程之Exchanger大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
@H_673_0@前言

今天我们来分享最后多线程最后一个工具类组件,之后我们会继续探索多线程的相关知识:线程池、并发容器和框架,然后就是总结和查漏补缺。

今天的内容很简单,内容也不太多,但是应用场景很典型,可以解决我们实际开发中数据对比的应用需求,好了,我们直接开始吧。

@H_673_0@Exchanger

exchanger也是jdk1.5引入的,主要用来解决线程之间数据交换的问题,和它的字面意思一样,exchanger主要是用来交换数据的,需要注意的是,交换数据的时候只能是两个(一对)线程两两交换,下面我们直接看示例代码:

public class Example {
    private final static Exchanger<String> exchanger = new Exchanger<>();

    public static void main(String[] args) {
        Executorservice executorservice = Executors.newFixedThreadPool(4);
        executorservice.execute(() -> {
            String taskStr = "10只羊";
            try {
                System.out.println("我是task1,正在等待交换,我有" + taskStr );
                String exchange = exchanger.exchange(taskStr);
                System.out.println("交换完成,task1获得:" + exchangE);
            } catch (InterruptedException E) {
                e.printStackTrace();
            }
        });

        executorservice.execute(() -> {
            String taskStr = "一头牛";
            try {
                System.out.println("我是task2,正在等待交换,我有" + taskStr );
                String exchange = exchanger.exchange(taskStr);
                System.out.println("交换完成,task2获得:" + exchangE);
            } catch (InterruptedException E) {
                e.printStackTrace();
            }
        });

        executorservice.execute(() -> {
            String taskStr = "50只鸡";
            try {
                System.out.println("我是task3,正在等待交换,我有" + taskStr );
                String exchange = exchanger.exchange(taskStr);
                System.out.println("交换完成,task3获得:" + exchangE);
            } catch (InterruptedException E) {
                e.printStackTrace();
            }
        });
        executorservice.execute(() -> {
            String taskStr = "40只鸭";
            try {
                System.out.println("我是task4,正在等待交换,我有" + taskStr );
                String exchange = exchanger.exchange(taskStr);
                System.out.println("交换完成,task4获得:" + exchangE);
            } catch (InterruptedException E) {
                e.printStackTrace();
            }
        });

        executorservice.shutdown();
    }
}

在上面的代码中,我们定义了一个交换器Exchanger,它本身是支持泛型的,这里我们定义的是String,然后定义了一个线程池,通过线程池分别启动四个线程,在四个线程中,都有这样一行代码:

String exchange = exchanger.exchange(taskStr);

它的作用就是和其他线程交换数据,并拿到交换后的数据,然后我们运行示例代码:

多线程之Exchanger

数据交换前,他们分别拥有10只羊,一头牛,50只鸡,40只鸭,交换后task2拿到task1的牛,task1拿到task2的羊,其他的也一样,之所以用这个例子,是因为它的交换过程确实很像原始社会的以物易物。

这里需要注意的是,交换数据的线程数量必须为双数,否则线程会一直被exchange方法阻塞,这里我们把最后一个线程先删除掉,然后运行:

多线程之Exchanger

因为没有线程再与task3进行数据交换,所以线程被阻塞了。

当然有时候,阻塞并非是人为的,而是在某些特殊情况下发生,为了避免因为这种情况导致线程持续阻塞,我们可以用exchanger的另一个方法:

多线程之Exchanger

这个方法支持设定超时时间,如果到设定时间依然没有数据交换,该方法会抛出TimeoutException异常:

多线程之Exchanger

关于exchanger的应用场景,我能想到的就两个,一个就是数据校验,两个线程同时操作同一批数据,我们可以对数据最终的一致性做校验,互相验证,比如两个excel的数据比对;另外一个场景和这个很类似,就是我们在实际开发经常会遇到方法A的运行条件需要根据B的运行结果进行优化调整,这时候我们就可以通过exchanger来来进行数据交换,然后再继续触发相关操作。

@H_673_0@总结

exchanger最大的优点是她可以在运行的过程中交换数据,其他的应用场景在遇到具体问题的时候再进一步分析吧。好了,exchanger的相关内容就到这里。

今天还要补充一个小知识,是关于@H_132_9@mysql的,是一个小知识点,也是线上发现的一个小问题,具体来说就是@H_132_9@mysql的求和语句,如果求和字段的值全部为null,那么最终的求和结果是null,而不是0,这样就会有潜在的空指针异常:

SELEct course_type, sum(order_id) from course GROUP BY course_type

因为order_id都是null,所以最终sum(order_id)就是null:

多线程之Exchanger

这样如果你用包装类接收sum(order_id)就是null,后续在操作它的时候一定要做空指针校验,否则就是个线上bug。好了,就这么多,over

大佬总结

以上是大佬教程为你收集整理的多线程之Exchanger全部内容,希望文章能够帮你解决多线程之Exchanger所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。