Java學習筆記之多線程

1.實現多線程

1.1進程
進程:是正在運行的程序。

  • 是系統進行資源分配和調用的獨立單位;
  • 每一個進程都有它自己的內存空間和系統資源。
    1.2線程
    線程:是進程中的單個順序控制流,是一條執行路經。
  • 單線程:一個進程如果只有一條執行路經,則爲單線程程序;
  • 多線程:一個進程如果有多條執行路經,則爲多線程程序。
    1.3多線程的實現方式
    方式1:
  • 定義一個類MyThread繼承Thread類;
  • 在MyThread類中重寫run()方法;
  • 創建MyThread類的對象;
  • 啓動線程。
    1.4設置和獲取線程名稱
    Thread類中設置和獲取線程名稱的方法
  • void setName(String name):將此線程的名稱更改爲等於參數name;
  • String getName():返回此線程的名稱;
  • 通過構造方法也可以設置線程名稱。
    如何獲取main()方法所在的線程名稱?
  • public static Thread currentThread():返回對當前正在執行的線程對象的引用。
    1.5 線程調度
    線程有兩種調度模型:
  • 分時調度模型:所有線程輪流使用CPU的使用權,平均分配每個線程佔用CPU的時間片;
  • 搶佔調度模型:優先讓優先級高的線程使用CPU,如果線程的優先級相同,那麼會隨機選擇一個,優先級高的線程獲取的CPU時間片相對多一些。

Java使用的是搶佔式調度模型。
假如計算機只有一個CPU,那麼CPU在某一時刻只能執行一條指令,線程只有得到CPU時間片,也就是使用權,纔可以執行指令。所以說多線程程序的執行是有隨機性,因爲誰搶到CPU的使用權是不一定的。

Thread類中設置和獲取線程優先級的方法:

  • public final int getPriority():返回此線程的優先級;
  • public final void setPriority(int new Priority):更改此線程的優先級。
    1.6線程控制
方法名 說明
static void sleep(long millis) 是當前正在執行的線程停留(暫停執行)指定的毫秒數
void join() 等待這個線程死亡
void setDaemon(boolean on) 將此線程標記爲守護線程,當運行的線程都是守護線程時,Java虛擬機將推出

1.7 線程生命週期
在這裏插入圖片描述1.8 多線程的實現方式
方式2:實現Runnable接口

  • 定義一個類MyRunnable實現Runnable接口;
  • 在MyRunnable類中重寫run()方法;
  • 創建MyRunnable類中的對象;
  • 創建Thread類的對象,把MyRunnable對象作爲構造方法的參數;
  • 啓動線程。
    多線程的實現方案有兩種:
  • 繼承Thread類;
  • 實現Runnable接口;
    相比繼承Thread類,實現Runnable接口的好處
  • 避免了Java單繼承的侷限性;
  • 適合多個相同程序的代碼去處理同一個資源的情況,把線程和程序的代碼、數據有效分離,較好的體現了面向對象的設計思想。

2. 線程同步

2.1 數據安全問題
判斷多線程程序是否會有數據安全問題的標準:

  • 是否是多線程環境;
  • 是否有共享數據;
  • 是否有多條語句操作共享數據;

如何解決多線程安全問題?

  • 基本思想:讓程序沒有安全問題的環境;
    怎麼實現?

  • 把多條語句操作共享數據的代碼給鎖起來,讓任意時刻只可能有一個線程執行即可。
    2.2 同步代碼塊
    鎖多條語句操作共享數據,可以使用同步代碼塊實現。

  • 格式:

  • synchronized(任意對象){

  • 多條語句操作共享數據的代碼

  • }

  • synchronized(任意對象):就相當於給代碼加鎖了,任意對象就可以看成是一把鎖。
    同步的好處和弊端:

  • 好處:解決了多線程的數據安全問題;

  • 壞處:當線程很多時,因爲每個線程都會去判斷同步上的鎖,這是很耗費資源的,無形中會降低程序的運行效率。
    2.3 同步方法
    同步方法:就是把synchronized關鍵字加到方法上。

  • 格式:修飾符synchronized返回值類型方法名(方法參數){ }。
    同步方法的鎖對象是什麼呢?

  • this
    同步靜態方法:就是把synchronzed關鍵字加到靜態方法上

  • 格式:修飾符 static synchronzed返回值類型 方法名(方法參數){ }
    同步靜態方法的鎖對象是什麼呢?

  • 類名.class
    2.4 線程安全的類
    StringBuffer

  • 線程安全,可變的字符序列

  • 從版本JDK5開始,被StringBuilder替代。通常應該使用StringBuilder類,因爲它支持所有相同的操作,但它更快,因爲它不執行同步。
    Vector

  • 從Java2平臺v1.2開始,該類改進了List接口,使其成爲Java Collections Framework的成員。與新的集合實現不同,Vector被同步。如果不需要線程安全的實現,建議使用ArrayList代替Vector.
    Hashtable

  • 該類實現了一個哈希表,它將鍵映射到值。任何非null對象都可以用作鍵或者值;

  • 從Java2平臺v1.2開始,該類進行了改進,實現了Map接口,使其成爲Java Collections Framework的成員。與新的集合實現不同,Hashtable被同步,如果不需要線程安全的實現,建議使用HashMap代替Hashtable。
    2.5 Lock鎖
    雖然我們可以理解同步代碼塊和同步方法的鎖對象問題,但是我們並沒有直接看到在哪裏加上了鎖,爲了更清晰的表達如何加鎖,JDK5以後提供了一個新的鎖對象Lock。
    Lock實現提供比較使用synchronized方法和語句可以獲得更廣泛的鎖定操作。
    Lock中提供了獲得鎖和釋放鎖的方法。

  • void lock():獲得鎖

  • void unlock():釋放鎖
    Lock是接口不能直接實例化,這裏採用它的實現類ReentrantLock來實例化。
    ReentrantLock的構造方法

  • ReentrantLock():創建一個ReentrantLock的實例。
    3.1生產者消費者模式
    爲了體現生產者和消費者過程中的等待和喚醒,Java就提供了幾個方法供我們使用,這幾個方法在Object類中。
    Object類中的等待和喚醒方法:

方法名 說明
void wait() 導致當前線程等待,直到另一個線程調用該對象的notify()方法或notifyAll()方法
void notify() 喚醒正在等待對象監視器的單個線程
void notifyAll() 喚醒正在等待對象監視器的所有線程
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章