2015-11-18-線程總結篇1

概念和原理

操作系統中線程和進程的概念

線程是指進程中的一個執行流程,一個進程中可以運行多個線程。線程總是屬於某個進程,進程中的多個線程共享進程的內存。

Java中的線程

每個線程都有一個調用棧,即使不在程序中創建任何新的線程,線程也在後臺運行着。
一個Java應用總是從main()方法開始運行,main()方法運行在主線程內。
線程總體分兩類:用戶線程和守候線程。當所有用戶線程執行完畢時,JVM自動關閉。但是守候線程卻不獨立於JVM,守候線程一般是由操作系統或者用戶自己創建的。

創建和啓動

定義和實例化線程

  • 繼承java.lang.Thread類,直接通過new來實例化。
  • 實現java.lang.Runnable接口,用Thread的構造方法來實例化。

啓動線程

在線程的Thread對象上調用start()方法,之後發生了一系列複雜的事情:


  • 啓動新的執行線程(具有新的調用棧);
  • 該線程從新狀態轉移到可運行狀態;
  • 當該線程獲得機會執行時,其目標run()方法將運行。

線程的調度是JVM的一部分,在一個CPU的機器上上,實際上一次只能運行一個線程。一次只有一個線程棧執行。JVM線程調度程序決定實際運行哪個處於可運行狀態的線程。

線程的狀態

  • 新狀態
  • 可運行狀態
  • 運行狀態
  • 等待/阻塞/睡眠狀態
  • 死亡態

線程被阻止運行

不考慮IO阻塞的情況下,有如下3中情況:

  • 睡眠;
  • 等待;
  • 因爲需要一個對象的鎖定而被阻塞。

睡眠Thread.sleep(long millis)

當線程睡眠時,它入睡在某個地方,在甦醒之前不會返回到可運行狀態。當睡眠時間到期,則返回到可運行狀態。
Thread.sleep()使當前線程睡眠至少多少毫秒(儘管它可能在指定的時間之前被中斷)。

讓步Thread.yield()

調用Thread.yield():不能保障太多事情,儘管通常它會讓當前運行線程回到可運行性狀態,使得有相同優先級的線程有機會執行。
yield()從未導致線程轉到等待/睡眠/阻塞狀態。在大多數情況下,yield()將導致線程從運行狀態轉到可運行狀態,但有可能沒有效果。

線程總是存在優先級,優先級範圍在1~10之間。JVM線程調度程序是基於優先級的搶先調度機制。在大多數情況下,當前運行的線程優先級將大於或等於線程池中任何線程的優先級。但這僅僅是大多數情況。

join()

Thread的非靜態方法join()讓一個線程B“加入”到另外一個線程A的尾部。在A執行完畢之前,B不能工作。
然而,如果它加入的線程沒有存活,則當前線程不需要停止。

其他

還有下面幾種特殊情況可能使線程離開運行狀態:
1、線程的run()方法完成。
2、在對象上調用wait()方法(不是在線程上調用)。
3、線程不能在對象上獲得鎖定,它正試圖運行該對象的方法代碼。
4、線程調度程序可以決定將當前運行狀態移動到可運行狀態,以便讓另一個線程獲得運行機會,而不需要任何理由。

線程的同步與鎖

Java中每個對象都有一個內置鎖。
當程序運行到非靜態的synchronized同步方法上時,自動獲得與正在執行代碼類的當前實例(this實例)有關的鎖。獲得一個對象的鎖也稱爲獲取鎖、鎖定對象、在對象上鎖定或在對象上同步。
一個對象只有一個鎖。所以,如果一個線程獲得該鎖,就沒有其他線程可以獲得鎖,直到第一個線程釋放(或返回)鎖。這也意味着任何其他線程都不能進入該對象上的synchronized方法或代碼塊,直到該鎖被釋放。
當一個類已經很好的同步以保護它的數據時,這個類就稱爲“線程安全的”。

何時需要同步?
在多個線程同時訪問互斥(可交換)數據時,應該同步以保護數據,確保兩個線程不會同時修改更改它。

線程的交互

void notify()
喚醒在此對象監視器上等待的單個線程。
void notifyAll()
喚醒在此對象監視器上等待的所有線程。
void wait()
導致當前的線程等待,直到其他線程調用此對象的 notify() 方法或 notifyAll() 方法。

守護線程

public final void setDaemon(boolean on)將該線程標記爲守護線程或用戶線程。當正在運行的線程都是守護線程時,Java 虛擬機退出。
該方法必須在啓動線程前調用。
參考網址:http://lavasoft.blog.51cto.com/62575/222742

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章