多线程并发的使用学习与测试

Posted 编程技术小站

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程并发的使用学习与测试相关的知识,希望对你有一定的参考价值。

前提


之前写过一篇手记 ,得到许多不错的反馈。但依然有这样的问题,许多人已经知道并发有这些内容,也知道这些知识点该如何用,但是却不知道该如何在实际项目中使用。基于以上,这篇手记将在之前手记的基础上,继续介绍多线程并发的使用、学习与测试。


也希望这篇手记能帮助 的学员更好的学习课程。


使用


先说说多线程的使用。多线程本身是与我们开发的项目密不可分的,我们只要提供了接口,那么他就可能被多个线程同时调用,就会产生并发问题,因此开发者在实际开发中对多线程的理解至关重要。当然,这属于最基本的认识。


就这一方面而言,对于开发者及学过并发的学员,平时开发中需要掌握的主要包括:


  1. 先说涉及最多的。看到static修饰的变量时,能想到涉及到多线程资源共享。如果是可变的,需要注意变化中的线程安全;如果是不可变的,需要知道如何保证其不可变,而不是简单的放在那,当前代码没有修改他就认识他是不变的。

  2. 看到final、单例等定义时,能分析出是否是线程安全的。

  3. 在看到集合、Map等结果时候时,知道该选什么类更适合,以及什么时候适合使用并发类,什么时候适合使用普通的类,这里本质上有对线程封闭的理解。

  4. 在遇到SimpleDateFormat等线程不安全的类时,能知道相关的并发风险点

  5. 在需要完成一些大任务时,知道如何借助线程池等进行提速,以及借助AQS相关组件进行一些线程的调度

  6. 知道常用的线程安全手段,能根据场景去分析是否需要加锁来保证线程安全。


说了这么多,相信很多人已经能感受到并发在日常开发中的存在,也能对并发多一些认识。虽然你可能很难用上并发一些手段,但你需要知道你看到的代码是否有问题,并发问题更多的存在于一些细节的处理中。这也是很多学员问我,为什么不出一门关于并发实战性质的课程,而是选择根据在知识点的讲解过程中介绍使用他们的一些场景。同时,由于并发的知识点多而繁杂,单独一门课程的几个场景很难覆盖整个并发知识体系,这样直接会导致许多人学完了并发却还是和之前一样,只是巩固了一遍知识点,别人问起来心里依旧很虚。而且,如果为了覆盖知识点去刻意的在某些场景中使用并发的某些知识点,反而可能会造成很多误解,效果并不一定理想。


继续谈多线程的使用。之前介绍的是我们不得不处理的多线程,接下来介绍主动创建的多线程的使用,即我们在代码里主动使用多线程去处理一些业务。


  1. 提速,充分利用CPU:这个理解起来应该比较容易,同一个任务,多个线程同时处理,让很多处理并行,达到更快完成的目的。这里介绍的一个场景,之前项目做大发布,要清洗历史数据(比如要根据id取出某一行,并计算某个值填进去),由于数据量很大,单线程清洗可能要1个小时左右,为了能尽快完成,不影响发布的时间,因此我们把单线程改为10个线程并行,测试发现10个线程还是有些慢,后来调整为20个线程同时处理,这样最终在3min左右完成。

  2. 降速,协调资源的使用:刚说完提速,这里又说降速,许多人可能会很奇怪。这里举具体例子来说明一下,比如项目里要发短信,目前有第三方的限制是每秒最多发送10条,而每天高峰期时段每秒需要发送的短信量可能远高于10条,这时怎么办呢?就可以在发短信时引入线程池及多线程池处理,控制同时发短信的线程不超过10,这样就起到了降速的作用。

  3. 异步处理,解耦。通常我们在做一个业务实现时,都有主流程和次流程之分,比如我们用户下单时,同时还要完成记录核心日志(核心的日志可能要记录的数据库中)以及通知用户下单完成等非核心业务,这些非核心的业务在处理时,有时可能会很耗时,但出任何错还不能让主流程失败,出错了还需要重试慢慢完成,这种的就可以开启新的线程去处理,异步解耦,让主流程快速完成并返回。当然,也不能无限制的开启新线程,放在线程池里控制更好。


许多人不知道如何使用多线程,希望这几点总结能让加深你的理解。关于多线程的使用,不是背的,在什么场景该使用什么场景不该使用,而是需要结合实际场景分析,是否需要进行提速、降速、异步处理等,如此才能在工作中较好的使用多线程。


学习


之前在大致介绍过,这里就不做过多的讲解,做个简单的总结:


还是课程里这张图,这张图不是简单的覆盖了并发的知识点,而是希望你能将这幅图印在脑子里。当你向别人讲述并发时,能先从整体描述并发的几个大方面,然后能挨个大方面进行细化。这也是你学习并发比较好的方法,脑海中有这个图,你就可以迅速的把知识点过一遍,哪个知识点模糊了你可以去补充一下就可以了,而不是每次需要学习并发时都是从头来一遍,而且每次看完都感觉还差点啥。


这个方法呢,也特别适合在面试中使用。面试官在让你说说对并发的了解时,你能先整体概括再局部细化,会让你在这个环节大大加分。不少学员已经从中受益,希望这个也能帮助到你。当然,这种先整体概括再局部细化的方式,也适合大家学习其他方面的知识,会让你的记忆更深刻,后续巩固也容易很多。


测试


说了并发的使用与学习,之后就是验证了,也属于并发的测试。并发的测试通常可以选择通过接口和方法两个方向去验证,可以根据不同需要进行选择。


先说根据接口测试。这种的通常要借助工具,Postman、JMeter、Apache Bench(AB)等都是不错的选择,其中JMeter、Apache Bench(AB)更适合测试人员来使用,Postman更适合开发人员来使用。


再说说根据方法测试。方法的测试更适合写代码去测试,这里给出一个模板:


public class ConcurrencyTest {

    // 请求的总数

    public static int clientTotal = 5000;

    // 同时并发执行的线程数

    public static int threadTotal = 200;

    public static void main(String[] args) throws Exception {

        ExecutorService executorService = Executors.newCachedThreadPool();

        final Semaphore semaphore = new Semaphore(threadTotal);

        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);

        for (int i = 0; i < clientTotal ; i++) {

            executorService.execute(() -> {

                try {

                    semaphore.acquire();

                    testMethod();

                    semaphore.release();

                } catch (Exception e) {

                    log.error("exception", e);

                }

                countDownLatch.countDown();

            });

        }

        countDownLatch.await();

        executorService.shutdown();

        // 所有线程执行完,之后才能执行的部分

    }

    private static void testMethod() {

        // 待验证的方法

    }

}


testMethod这个方法替换为要测试的方法就可以了。如果不需要在所有线程执行完执行某些代码,可以去掉CountDownLatch的使用;如果不需要控制同一时间同时并行的线程数,可以去掉Semaphore的使用。


这里顺便补充一个技巧,有时为了让测试结果更明显一些,testMethod方法里可以考虑通过Thread.sleep方法让测试方法执行的慢一些,让并发测试的结果更显著。


另外有一点希望一定重要,在项目中,尤其是并发场景下,核心点要有日志记录核心变量的值,但一定不要使用System.out去输出日志,而我们通常讨论的slf4j、logback等,则是推荐使用的,因为他们会包含我们分析时能用到的:线程名称、代码行、及输出日志的时间等,System.out不光是没这些重要信息,而且在输出时使用了synchronized,这直接导致输出日志那里会出现线程阻塞。更多日志的规范可以参考我之前的手记:Java项目中使用log记录日志的一些总结。


实际项目中,尤其是在分布式系统里,很多问题的分析,我们都要依靠项目运行过程中输出的日志。线程名称、代码行、输出日志的时间、相关的变量值这几项又是分析过程中最关键的,希望大家能引起重视。


结尾



其他文章推荐







Java并发编程与高并发解决方案:

https://coding.imooc.com/class/195.html

Java开发企业级权限管理系统:

https://coding.imooc.com/class/149.html


欢迎转载和收藏,别忘了关注我哦~



以上是关于多线程并发的使用学习与测试的主要内容,如果未能解决你的问题,请参考以下文章

Java接口多线程并发测试

python-学习-python并发编程之多进程与多线程

Java多线程与并发---学习总结(很详细)

多线程与高并发线程安全

多线程与高并发线程安全

认识多线程与高并发