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 条评论
登录 后参与评论

相关文章

来自专栏Kirito的技术分享

给初中级JAVA准备的面试题

笔者作为一个今年刚毕业的初级JAVA,根据群里水友的讨论,也结合自己刚毕业时的一些面经,加上近期一点点在公司面试别人的经验,总结了如下的常见面试问题,适用于初级...

3868
来自专栏苦逼的码农

一文看懂https如何保证数据传输的安全性的

大家都知道,在客户端与服务器数据传输的过程中,http协议的传输是不安全的,也就是一般情况下http是明文传输的。但https协议的数据传输是安全的,也就是说h...

782
来自专栏后端技术探索

非Java程序员竟鲜有人真正理解DI和IOC

小编在后端圈也算是阅人无数了, 发现一个现象,Java程序员对于面向对象语言的基础知识整体掌握比较扎实,而类似PHP,Python的初级甚至中级程序员就比较薄弱...

1232
来自专栏更流畅、简洁的软件开发方式

【自然框架】用CMS的栏目举例,聊一聊从“一层”到“三层”的变化

  做CMS最基本的一个功能就是做一个栏目导航,如果这个导航想做成动态的(即需要从数据库里提取数据)那么要如何实现呢? 简单的方法——DataTable   ...

2089
来自专栏程序人生

谈谈系统设计的面试

这个题目我一直在考虑要不要写,因为有一天也许我们彼此会坐在一方小桌的两端,聊聊系统设计,而我这么做有泄题兜底之嫌。不过,考虑到不是所有的读者都会来 TubiTV...

3616
来自专栏haifeiWu与他朋友们的专栏

复杂业务下向Mysql导入30万条数据代码优化的踩坑记录

从毕业到现在第一次接触到超过30万条数据导入MySQL的场景(有点low),就是在顺丰公司接入我司EMM产品时需要将AD中的员工数据导入MySQL中,因此楼主负...

1204
来自专栏java达人

阿里面试题及相关参考链接(修订版)

似乎每个程序员都有一颗进阿里看看的好奇心,虽然很多人最后也从那座围城里走出来了,但没有去过阿里多多少少总有些遗憾吧。因此,我最近问了一些接到过阿里电话面试的朋友...

990
来自专栏Java呓语

命令模式(封装命令)

如果您是第一次阅读我的设计模式系列文章,建议先阅读设计模式开篇,希望能得到您宝贵的建议。

882
来自专栏牛客网

网易 Java面经19届实习一面(3.16日)二面(3.20日)

一面(3.16日) 1、自我介绍一下 2、快排相关的(原理、复杂度、使用场景) 3、问了ArrayList、LinkedList(问了我源码、底层实现原理) 4...

46110
来自专栏牛客网

爱奇艺现场面试总结

一面: java内存模型:问面试官是jmm还是jvm,说是jvm,说了说分区 堆内存:说了堆内存划分和理由,各种内存的分配流程,各类回收算法。 项目:略 mys...

5007

扫码关注云+社区