多線程--基礎概念

最近時間多,準備對多線程的一些知識進行溫故,讓自己有進一步的提升

多線程編程的一些基礎概念

什麼是進程和線程?兩者的區別是什麼?

1.進程:每個進程都有獨立的代碼和數據空間(進程上下文),進程間的切換會有較大的開銷,一個進程包含1–n個線程。(進程是資源分配的最小單位),比如window任務窗口中的.exe運行程序。
2.線程:同一類線程共享代碼和數據空間,每個線程有獨立的運行棧和程序計數器(PC),線程切換開銷小。(線程是cpu調度的最小單位)
進程與線程的區別:
a.多個線程的內部數據和狀態都是完全獨立的,而多線程是共享一塊內存空間和一組系統資源,有可能相互影響。
b.線程本身的數據通常只有寄存器數據,以及一個程序執行時使用的堆棧,所以線程的切換比進程切換的負擔要小。
c.一個進程可以包含一個線程或者多個線程
d.一個程序實現多個代碼同時交替運行就需要產生多個線程

多線程編程的目的?

最大限度地利用CPU資源,當某一個線程的處理不需要佔用CPU而只和I/O等資源進行打交道時。讓需要佔用CPU資源的其他線程有機會獲得CPU資源,從根本上來說,這就是多線程編程的最終目的。

Java多線程實現的方式:

1.繼承Thread類,Thread類也實現了Runnable接口,因此實現了Runable接口中的run方法;
2.實現Runabble接口
將我們要執行的代碼放入到run方法中,然後通過start()方法來啓動線程,start方法首先會爲線程的執行準備好系統資源,然後再去調用run方法。當 某個類繼承了Thread類之後,該類就叫做了一個線程類。

查看源代碼可以知道,當使用第一種方式來生成線程對象時,我們需要重寫run方法,因爲Thread類的run方法此時什麼事情也不做,所以需要我們重寫
當使用第二種方式生成線程對象時,我們需要實現Runable接口中的run方法。然後使用new Thread(new MyThread()) MyThread實現了Runable來生成線程對象。這時的線程對象的run方法或調用MyThread類的run方法。這樣我們編寫的run方法就執行了。

多線程的狀態:

這裏寫圖片描述
線程在一定條件下。狀態會發生變化。
線程變化的狀態轉換圖例如以下:
  1、新建狀態(New):新創建了一個線程對象。
  2、可運行狀態(Runnable):線程對象創建後,其它線程調用了該對象的start()方法,將分配資源。
該狀態的線程位於可執行線程池中,變得可執行,等待獲取CPU的使用權。
  3、執行狀態(Running):就緒狀態的線程獲取了CPU。執行程序代碼。
  4、堵塞狀態(Blocked):堵塞狀態是線程由於某種原因放棄CPU使用權。臨時停止執行。直到線程進入就緒狀態,纔有機會轉到執行狀態。
堵塞的情況分三種:
  (一)、等待堵塞:執行的線程執行wait()方法,JVM會把該線程放入等待池中。
  (二)、同步堵塞:執行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用。則JVM會把該線程放入鎖池中。
  (三)、其它堵塞:執行的線程執行sleep()或join()方法,或者發出了I/O請求時。JVM會把該線程置爲堵塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完成時。線程又一次轉入就緒狀態。
  5、死亡狀態(Dead):線程運行完了或者因異常退出了run()方法,該線程結束生命週期。

詳細說明:
1、線程的實現有兩種方式,一是繼承Thread類,二是實現Runnable接口,但無論如何,當我們new了這個對象後。線程就進入了初始狀態;
2、當該對象調用了start()方法,就進入可執行狀態;
3、進入可執行狀態後,當該對象被操作系統選中。獲得CPU時間片就會進入執行狀態;
4、進入執行狀態後情況就比較複雜了
    4.1run()方法或main()方法結束後,線程就進入終止狀態;
    4.2、當線程調用了自身的sleep()方法或其它線程的join()方法,就會進入堵塞狀態(該狀態既停止當前線程,但並不釋放所佔有的資源)。當sleep()結束或join()結束後。該線程進入可執行狀態,繼續等待OS分配時間片;
    4.3、線程調用了yield()方法,意思是放棄當前獲得的CPU時間片,回到可執行狀態,這時與其它進程處於同等競爭狀態,OS有可能會接着又讓這個進程進入執行狀態。
   4.4、當線程剛進入可執行狀態(注意,還沒執行),發現將要調用的資源被synchroniza(同步),獲取不到鎖標記。將會馬上進入鎖池狀態,等待獲取鎖標記(這時的鎖池裏或許已經有了其它線程在等待獲取鎖標記,這時它們處於隊列狀態,既先到先得),一旦線程獲得鎖標記後,就轉入可執行狀態。等待OS分配CPU時間片。
   4.5、當線程調用wait()方法後會進入等待隊列(進入這個狀態會釋放所佔有的全部資源,與堵塞狀態不同)。進入這個狀態後。是不能自己主動喚醒的,必須依靠其它線程調用notify()notifyAll()方法才幹被喚醒(因爲notify()僅僅是喚醒一個線程,但我們由不能確定詳細喚醒的是哪一個線程。或許我們須要喚醒的線程不可以被喚醒,因此在實際使用時,一般都用notifyAll()方法,喚醒有所線程),線程被喚醒後會進入鎖池。等待獲取鎖標記。

線程的優先級

1.線程的優先級是一個1-10的數字,線程總是存在優先級,優先級範圍在1~10之間,優先級的設置通過setPriority(8)進行設置,線程默認的優先級爲5。
2.設計程序的時候千萬不能依賴線程的優先級,因爲線程調度的優先級是沒有保證的。只能把線程的優先級當做一種程序優化的手段而已。
3.線程的優先級用1-10之間的整數表示,數值越大優先級越高。

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