1. 程式人生 > >多線程總結

多線程總結

color cnblogs 含義 發的 false 標識 不一定 net 類的屬性

一、對多線程的理解

  1.進程和線程

   程序是指令和數據的有序集合,本身沒有任何運行的含義,是一個靜態的概念。幾乎所有的操作系統都支持同時運行多個任務,一個任務通常就是一個程序,每個運行中的程序就是一個進程。當一個程序運行時,內部可能包含了多個順序執行流,每個順序執行流就是一個線程。一個程序只有一個進程,但一個進程可以有多個線程。

   進程:正在進行中的程序。其實進程就是一個應用程序運行時的內存分配空間。

   線程:程序的執行路徑。程序只有一條執行路徑就是單線程;程序有多條執行路徑就是多線程

  2.理解並發與並行
    思考:我們在一邊玩遊戲,一邊帶上耳機聽歌,請問玩遊戲與聽歌是同時進行的嗎?

      顯然不是,因為CPU在某一個時間點上只能做一件事,我們玩遊戲,CPU就切換到執行遊戲進程,聽歌,CPU就切換到聽歌進程;CPU就這樣反復做這高效率的切換動作,這種切換是隨機的,但是讓我們感覺到就是同時發生的,這就是並發的概念。

    並發:通過CPU調度算法,讓用戶看上去同時執行,實際上,是通過CPU在高速切換,並不是真正的額同時。

    並行:多個CPU實例或者多臺機器同時執行一段處理邏輯,這就是真正的同時;

    或這樣表述==>

    並發:指在同一時刻,只能有一條指令執行,但多個進程指令被快速輪換執行,使得在宏觀上具有多個進程同時執行的效果。

    並行:指在同一時刻,有多條指令在多個處理器上同時執行;

  3.多線程出現的原因(多線程的優點):

   1)為了解決負載均衡問題,充分利用CPU資源;

   2)為了提高CPU的使用率,采用多線程的方式去同時完成幾件事情而不互相幹擾;

   3)防止阻塞。如果我們使用單線程執行一個任務,如果碰到I/O操作(或其他耗時操作),後面的任務就要被阻塞,這時候CPU就處於空閑狀態。 如果是多線程的情況,就可以各自(交替)執行不同的操作,即使I/O阻塞,也不會影響另一個線程的運行;

   4)可以把程序中比較耗時的任務放到後臺去處理;

   5)優化用戶體驗,比如迅雷使用多線程同時下載多個文件。

二、創建線程的三種方式

  參考:https://www.cnblogs.com/colily/p/6690038.html和https://blog.csdn.net/u011240877/article/details/57202704

  1)實現 Runnable 接口;
  2)繼承 Thread重寫其 run 方法;
  3)實現 Callable 接口重寫 call 方法用 FutureTask 獲得結果;這一種是帶有返回值的。

三、線程的一些屬性

  1.優先級

  Thread 有個優先級字段:private int priority,值從 1 到 10 逐漸提高,默認為 5。

  線程的優先級可以在一定程度上影響它得到時間片的多少,也就是被處理的機會。有長耗時操作的線程,一般建議設置低優先級,確保處理器不會被獨占太久; 頻繁阻塞(休眠或者 I/O)的線程建議設置高優先級。

  2.守護線程(後臺線程)

  Thread 中有個布爾值標識當前線程是否為守護線程:private boolean daemon = false;該屬性需要在調用線程的 start() 方法之前調用。

四、線程控制(線程的一些常用的方法)

  1.Thread.sleep(long millis)

  使當前所在線程進入阻塞;只是讓出 CPU,並沒有釋放對象鎖;由於休眠時間結束後不一定會立即被 CPU 調度,因此線程休眠的時間可能大於傳入參數;如果被中斷會拋出 InterruptedException。

  2.join():表示線程合並,需要等待被調用線程結束後才可以執行。

ThreadJoin tj1 = new ThreadJoin();
ThreadJoin tj2 = new ThreadJoin();
ThreadJoin tj3 = new ThreadJoin();

tj1.start();
try {
    tj1.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}
// 等待線程tj1結束,才會執行線程tj2和tj3
tj2.start();
tj3.start();

  3.Thread.yield():暫停當前正在執行的線程對象。和 sleep() 方法不同的是,它不會進入到阻塞狀態,而是進入到就緒狀態。

  4.setDaemon(boolean on):將該線程標記為守護線程或用戶線程。當正在運行的線程都是守護線程(也叫後臺線程)時,Java 虛擬機退出。 該方法必須在啟動線程前調用。

  5.interrupt():中斷線程。

五、什麽是線程安全,如何保證線程安全

  1.線程安全

    1)簡單來說,線程安全就是: 在多線程環境中,能永遠保證程序的正確性。

    2)只有存在共享數據時才需要考慮線程安全問題。其中, 方法區和堆就是主要的線程共享區域。那麽就是說共享對象只可能是類的屬性域或靜態域。

    3)當一個類被多個線程進行訪問並且正確運行,它就是線程安全的。

    4)當多個線程訪問某個類時,不管運行時環境采用何種調度方式或者這些線程將如何交替執行,並且在主調代碼中不需要任何額外的同步或者協同,這個類都能表現出正確的行為,那麽就稱這個類是線程安全的。

  2.判斷是否有線程安全問題?

    1)是否是多線程環境;2)是否有共享數據;3)是否有多條語句操作共享數據。

  3.如何解決多線程安全問題:把多個語句操作共享數據的代碼鎖起來,讓任意時刻只能有一個線程執行。(多線程同步機制)

六、線程同步

  1)7種同步方式:參考 https://www.cnblogs.com/XHJT/p/3897440.html

  2)同步代碼塊的鎖對象:任意對象

  3)同步方法的鎖對象:this

  4)同步靜態方法的鎖對象:類的字節碼文件對象(類.class)

七、同步的弊端

  1)效率低;2)可能產生死鎖。

  死鎖:兩個或兩個以上的線程在爭奪資源的過程中,發生相互等待的現象。(相互等待對方釋放鎖)

八、線程的狀態

  線程的5種狀態:新建(New),就緒(Runnable),運行(Running),阻塞(Blocked),死亡(Dead)

  線程的狀態轉換圖:見我的另一篇博客。

多線程總結