专栏首页互联网研发闲思录java多线程开发容易犯的错误

java多线程开发容易犯的错误

      昨天在社区上看到有人讨论多线程使用,多线程遇到一些问题以及一些使用技巧记录一下。为什么要使用多线程,

不能是为了用而用,和设计模式一样用的合理,会让程序更易于理解,用的不合理反而会让程序变得更难理解。

      过去使用场景有,cms内容管理系统多个编辑配置频道,将多个频道以及频道下文章发布成静态html,如果单线程

我们一般是这么去做的,首先通过sql取得全部频道,对频道进行遍历,取到每个频道在取频道下文章列表,然后遍历

文章列表的每一片文章,对每一篇文章标题、作者、简介、内容、图片取出根据配置模版生成html文件,文章列表执

行完一个取下一个频道循环执行。直到所有频道发布完毕,这是整个站点发布完毕,发布过程结束。

      上述方式很好完成了发布这个需求,但是作为研发的我们有没有更好、更快方式去搞定这件事情呢?一定有的,

只要我们去想。如果我们将每个频道发布看成一个任务,通过多线程方式并行同时去发布频道那发布时间10个频道

理论上会成为原来10分之一,整个发布减少了时间、提升了性能,用户能够更快看到新内容、新文章。

      用多线程要对线程、线程池、同步机制不断学习,因为多线程是好东西,但坑也是很多。稍有不慎就会导致程序bug、

甚至死锁、线上cpu100%服务不可用。

public class MyVisiblility{
     private static boolean ready;
     private static int number;    
     private static class MyReaderThread extends Thread{
          public void run(){ //读线程
               while(!ready) 
                  Thread.yield();
               System.out.println(number);
          }
     public static void main(String [] args){ //主线程 
          new MyReaderThread().start();
          number=42;
          ready=true;
     }}

      这段程序有很大几率输出结果可能为0,也可能是死循环,跟我们期待不一样,原因是什么呢?线程对共享变量

的所有操作都必须在自己的工作内存中进行,不能直接从主线程中获取。因为副本主线程修改子线程为能收到。当

number变量不可见时输出结果为0,当ready不可见时子线程死循环。解决问题方式将变量加上volatile修饰词解决

多线程变量可见性问题。

即程序改为:

public class MyVisiblility{
     private static volatile boolean ready;
     private static volatile int number;    
     private static class MyReaderThread extends Thread{
          public void run(){ //读线程
               while(!ready) 
                  Thread.yield();
               System.out.println(number);
          }
     public static void main(String [] args){ //主线程 
          new MyReaderThread().start();
          number=42;
          ready=true;
     }}

个性化推荐系统(八)--- 机器学习深度学习召回集扩量这篇文章通过CountDownLatch实现主线程等待

多个计算线程同步,要将CountDownLatch.down()方法用在finally方法中,不要再其他地方,昨天review发现

线上再一个返回逻辑中用了CountDownLatch.down(),再finally中也用了,而finally中时一定会执行的,这时

相当于执行了两次主线程有几率不等待剩余线程向下执行,导致程序偶发bug,这个其实是对finally理解不到位。

再有就是经典HashMap用于多线程而没有用ConcurrentHashMap导致线上服务cpu100%详见这篇记一次双11大促压测线上服务cpu100%

再有就是ThreadLocal变量在ThreadPoolExecuter线程同时使用时,程序异常相见警惕ThreadLocal和ThreadPoolExecutor同时使用

      多线程使用好会提升程序性能简化程序实现,使用不好会引入bug、cpu100%、死循环、程序偶发不正确,并且

还不容易定位。这就要求我们要不断研究学习多线程技术,以保证优雅正确将多线程应用到线上服务以及其他各种场景。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 京东个性化推荐系统实战(上)

           推荐系统核心任务是排序,从线上服务角度看,就是将数据从给定集合中数据选择出来,选出后根据一定规则策略方法 进行排序。        线上服务要根据...

    杉枫
  • 个性化推荐系统(三)---推荐系统意义一点思考

            个性化推荐是随着移动互联网发展不断发展起来的,国内应用个性化推荐技术最早应该是豆瓣,在web2.0兴起时做了很多尝试,给网民带来很多新鲜感觉、体...

    杉枫
  • 爬虫抓取技术

      互联网数据很多,发现好内容并能持续不断的抓取是一项不简单的工作。 反反爬虫 爬虫的固定套路也就那么多,各种网站爬取策略的不同就在于网站的反爬虫机制不同,因此...

    杉枫
  • 【小家java】泛型--那些年我们一起躺过的坑

    java的泛型是在JDK5开始出现的,在各种设计模式中有非常广泛的应用,比如设计一些基类等,参数化类型(具体的类型参数化)对扩展性能提供很好的支持,避免了不安全...

    YourBatman
  • 我是如何通过CSRF拿到Shell的

    织梦内容管理系统(DedeCms) 以简单、实用、开源而闻名,是国内最知名的PHP开源网站管理系统,也是使用用户最多的PHP类CMS系统,在经历多年的发展,目前...

    FB客服
  • tRNAdb:综合序列和二级结构的tRNA数据库

    tRNAdb 收录了来自577个物种的12000个tRNA基因和来自104个物种的623条tRNA序列,除了基本的序列信息外,还提供了二级结构的数据。

    生信修炼手册
  • 2020-chrome谷歌浏览器插件提示“程序包无效”的解决办法

    斑马
  • Spark集群安装 原

        Spark的版本1.6.0,Scala的版本2.12,jdk版本1.8。最近使用spark,在这里记录下。

    克虏伯
  • 使用 redis-shake 迁移 redis-cluster集群

        IDC上云, 有2套redis-cluster需要迁移到云上。 这里我们使用 redis-shake 来做迁移操作。

    二狗不要跑
  • Java虚拟机--运行时数据区与内存溢出

    存放的数据是JVM加载的类信息,常量,静态变量和编译器编译后的代码等,这里要注意的是JDK1.8之后已经将这个方法区删除了,使用元空间,metaspace代...

    王小明_HIT

扫码关注云+社区

领取腾讯云代金券