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%、死循環、程序偶發不正確,並且

還不容易定位。這就要求我們要不斷研究學習多線程技術,以保證優雅正確將多線程應用到線上服務以及其他各種場景。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM