java 多線程

java 多線程

原文鏈接

前言

線程安全出現的問題例子:

比如一個 ArrayList 類,在添加一個元素的時候,它可能會有兩步來完成:1. 在 Items[Size] 的位置存放此元素;2. 增大 Size 的值。

在單線程運行的情況下,如果 Size = 0,添加一個元素后,此元素在位置 0,而且 Size=1;

而如果是在多線程情況下,比如有兩個線程,線程 A 先將元素1存放在位置 0。但是此時 CPU 調度線程A暫停,線程 B 得到運行的機會。線程B向此 ArrayList 添加元素2,因為此時 Size 仍然等于 0 (注意,我們假設的是添加一個元素是要兩個步驟,而線程A僅僅完成了步驟1),所以線程B也將元素存放在位置0。然后線程A和線程B都繼續運行,都增加 Size 的值,結果Size等于2。

那好,我們來看看 ArrayList 的情況,期望的元素應該有2個,而實際只有一個元素,造成丟失元素,而且Size 等于 2。這就是“線程不安全”了。

線程安全主要是由于:共享變量及共享變量的修改引起的問題。

相應的解決方法是:

線程中的局部變量不需要同步;線程內操作的,同時線程外需要用到的,需要同步!

講解

如果對什么是線程、什么是進程仍存有疑惑,請先Google之,因為這兩個概念不在本文的范圍之內。

用多線程只有一個目的,那就是更好的利用cpu的資源,因為所有的多線程代碼都可以用單線程來實現。說這個話其實只有一半對,因為反應“多角色”的程序代碼,最起碼每個角色要給他一個線程吧,否則連實際場景都無法模擬,當然也沒法說能用單線程來實現:比如最常見的“生產者,消費者模型”。

很多人都對其中的一些概念不夠明確,如同步、并發等等,讓我們先建立一個數據字典,以免產生誤會。

  • 多線程:指的是這個程序(一個進程)運行時產生了不止一個線程
  • 并行與并發
    • 并行:多個cpu實例或者多臺機器同時執行一段處理邏輯,是真正的同時。
    • 并發:通過cpu調度算法,讓用戶看上去同時執行,實際上從cpu操作層面不是真正的同時。并發往往在場景中有公用的資源,那么針對這個公用的資源往往產生瓶頸,我們會用TPS或者QPS來反應這個系統的處理能力。

好了,讓我們開始吧。我準備分成幾部分來總結涉及到多線程的內容:

  • 扎好馬步:線程的狀態
  • 內功心法:每個對象都有的方法(機制)
  • 太祖長拳:基本線程類
  • 九陰真經:高級多線程控制類

找好馬步:線程的狀態

如下圖所示:

線程狀態

內功心法:每個對象都有的方法(機制)

synchronized, wait, notify 是任何對象都具有的同步工具。

太祖長拳:基本線程類

基本線程類指的是Thread類,Runnable接口,Callable接口,Thread 類實現了Runnable接口.

九陰真經:高級多線程控制類

以上都屬于內功心法,接下來是實際項目中常用到的工具了,Java1.5提供了一個非常高效實用的多線程包:java.util.concurrent, 提供了大量高級工具,可以幫助開發者編寫高效、易維護、結構清晰的Java多線程程序。

1.ThreadLocal類

用處:保存線程的獨立變量。對一個線程類(繼承自Thread)
當使用ThreadLocal維護變量時,ThreadLocal為每個使用該變量的線程提供獨立的變量副本,所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應的副本。常用于用戶登錄控制,如記錄session信息。

實現:每個Thread都持有一個TreadLocalMap類型的變量(該類是一個輕量級的Map,功能與map一樣,區別是桶里放的是entry而不是entry的鏈表。功能還是一個map。)以本身為key,以目標為value。
主要方法是get()和set(T a),set之后在map里維護一個threadLocal -> a,get時將a返回。ThreadLocal是一個特殊的容器。

原子類(AtomicInteger、AtomicBoolean……)

5.管理類(最常用)

管理類的概念比較泛,用于管理線程,本身不是多線程的,但提供了一些機制來利用上述的工具做一些封裝。

了解到的值得一提的管理類:ThreadPoolExecutor和 JMX框架下的系統級管理類 ThreadMXBean

ThreadPoolExecutor

如果不了解這個類,應該了解前面提到的ExecutorService,開一個自己的線程池非常方便:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 前言 個人認為,學習,內容越多、越雜的知識,越需要進行深刻的總結,這樣才能記憶深刻,將知識變成自己的。這篇文章主要...
    堯淳閱讀 684評論 0 17
  • 作者:月的倉頡文章源自:http://www.cnblogs.com/xrq730/p/5060921.html ...
    IT程序獅閱讀 1,590評論 2 73
  • 親愛的銘兒: 媽媽的寶貝,2016年6月,你將要中考,這是你人生的第一個轉折點,媽媽為你加油。當獲悉你已收到福泉...
    綻放唐朝閱讀 396評論 0 1
  • 想 凝望 苦笑聲 滿腹愁腸 憶那人臉龐 俊逸陽剛 摸頭殺 難忘 你
    執明珠魅閱讀 257評論 0 1
  • 2017年11月16日 星期六 晴 今天我和同學約好了一起去玩密室逃脫,所以昨晚我興奮的一晚上都沒有睡好。...
    勝利者句國豪閱讀 201評論 0 0