編寫多線程java程序時需要注意哪些問題?(來自於effective java se)

   多線程編程可能會出現很多問題,而且有時問題無法重現,或不知什麼時候會重現。或測試通過,實際運行時卻出現了問題。或者在不同的虛擬機和編譯器上有不同的

   表現。這也是一個面試常見題,這個問題很大,有很多方面,下面談談我的一點體會:

    1)並不是線程越多越好。

       多線程是爲了A網絡服務面對同時的大量客戶端請求,或同時請求大量地址如網絡爬蟲 

             B,涉及GUI的圖形界面編程,可以提高響應速度

             C充分利用多核CPU的特點,提高程序執行的效率。

       一般也要十幾個到幾十個,具體情況具體分析

    2)正確同步訪問共享的易變數據

         關於同步synchronized的兩種作用A訪問串行化,使可變對象在被外界觀測時一直處於一種一致性的狀態,否則不可訪問(mutual exclusion)

                  B使一個線程對它的修改對於其他線程是可見的(communication effects)

         除long和double外的所有基本類型,或對象的引用的讀寫都是原子的。這保證了A,但沒有保證B,所以需要volatile關鍵字

         (the volatile modifier performs no mutual exclusion, it

                  guarantees that any thread that reads the field will see the most recently written value)

 

                   自增運算不是原子的。the increment operator (++) is not atomic

 

                   可以共享不變對象就不會產生這樣的問題。(effectively immutable,safe publication)

 

                   總結,當一些線程共享可變數據時,每個線程的讀寫這個數據的方法都必須顯示的使用同步

                   In summary, when multiple threads share mutable data, each thread that

          reads or writes the data must perform synchronization

    3)避免過分同步

         過分同步可能會引起性能降低,死鎖,甚至非確定性的行爲( nondeterministic behavior.)

                  (A)To avoid liveness and safety failures, never cede control to the client within a synchronized method or block

                     換句話說,在同步區域,不要調用被設計爲Override的方法,或客戶端提供的 function object。

                   (B)在同步方法中要儘可能做更少的事 As a rule, you should do as little work as possible inside synchronized regions.

                      如果一個可變類是被用於多線程共享訪問,你應該使它線程安全。因爲內部同步比鎖住整個對象的效率要高得多

                     (You should make a mutable class thread-safe (Item 70) if it is intended for

            concurrent use and you can achieve significantly higher concurrency by synchro-

            nizing internally than you could by locking the entire object externally)

           如果不是這樣,就不應該使用同步。就如同StringBuffer一樣,現在它被StringBuilder替代了

          In summary, to avoid deadlock and data corruption, never call an alien method

           from within a synchronized region. More generally, try to limit the amount of

           work that you do from within synchronized regions. When you are designing a

           mutable class, think about whether it should do its own synchronization. In the

           modern multicore era, it is more important than ever not to synchronize exces-

           sively. Synchronize your class internally only  if there is a good reason to do so,

           and document your decision clearly

    4)Prefer executors and tasks to threads

 

           ExecutorService executor = Executors.newSingleThreadExecutor();

            executor.execute(runnable);

            executor.shutdown();

 

         java.util.concurrent.Executors 的工廠方法提供了大多數情況下你所需要的Executor,如果你想要定製一個,那麼直接使用ThreadPoolExecutor。

 

                   ScheduledThreadPoolExecutor

 

            In essence, the Executor Framework does for execution what the Collections Framework did for aggregation. 

    5)Prefer concurrency utilities to wait and notify

    6)Use lazy initialization judiciously

         7)Don’t depend on the thread scheduler

         8)Avoid thread groups

發佈了49 篇原創文章 · 獲贊 3 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章