默寫:
1.程式設計題
分別使用兩種方式啟動一個執行緒,在該執行緒的run()方法中列印1 ~ 20之間的整數。

作業:
1.思考:建立和啟動執行緒兩種方式之間的區別?

  a.自定義類繼承Thread類並重寫run()方法,建立該類的例項去呼叫start()方法。
    b.自定義類實現Runnable介面並重寫run()方法,建立該類的例項作為建立Thread類
      例項的實參然後再去呼叫start()方法。
 
當使用Runnable引用作為引數構造物件時(儘量理解):
    a.new Runnable介面的實現類物件傳遞給Thread類的構造方法。
    b.Thread類的構造方法將實現類物件傳遞給init()方法。
    c.init方法的內部將實現類物件傳遞給成員變數target。
    d.在run()方法中判斷成員變數target是否為空,若不為空則呼叫run()方法。
      由於target引用指向實現類的物件,因此在執行階段呼叫實現類中的run()方法。

解析:
a.繼承的方式程式碼相對簡單,但Java語言支援單繼承,若繼承Thread類則無法
繼承其他父類.
b.實現介面的方式程式碼相對複雜,但不影響該類繼承其他父類,並且支援多實現,
從專案的可維護性上來說,推薦使用該方式。

今天內容:
(1)執行緒類的常用方法
(2)執行緒的同步機制
(3)網路程式設計的常識
(4)基於tcp協議的程式設計模型

1.執行緒類的常用方法
static void yield() - 用於讓出當前執行緒執行權,也就是暫停執行當前執行緒,
轉而執行其他執行緒(瞭解)。
static void sleep(long millis) - 用於讓當前執行緒休眠引數指定的毫秒數。
static void sleep(long millis, int nanos) -用於讓當前執行緒休眠指定毫秒+納秒
- 1秒=1000毫秒 1毫秒=1000微秒 1微秒 = 1000納秒
void interrupt() - 中斷執行緒,通常用於打斷執行緒的休眠操作(瞭解)。
void setPriority(int newPriority) - 用於更改執行緒的優先順序為引數指定的數值。
int getPriority() - 用於獲取執行緒的優先順序並返回。
- 優先順序高的執行緒並不一定先執行,只是獲取到時間片的機會更多一些。
void join() - 用於等待該執行緒終止。
void join(long millis) - 等待該執行緒終止的時間最長為引數指定的毫秒。
void join(long millis, int nanos)
- 等待該執行緒終止的最長時間為引數指定的毫秒 + 引數指定的納秒。
void setDaemon(boolean on) - 用於將該執行緒設定為守護執行緒/使用者執行緒。
- 守護執行緒用於守護其他執行緒,當其他執行緒都結束時,守護執行緒隨之結束。

要求重點掌握的方法:
sleep()方法 和 join()方法。

2.執行緒的同步機制(重點)
複習:
StringBuffer類屬於執行緒安全的類,支援執行緒的同步機制,執行效率低。
StringBuilder類屬於非執行緒安全的類,不支援執行緒的同步機制,執行效率高。

2.1 基本概念
當多個執行緒同時訪問同一種共享資源時可能會造成資料的不一致性,此時就需要進行執行緒之間的協調,而執行緒之間的協調和通訊就叫做執行緒的同步機制。

2.2 解決方案
由程式案例可知:當多個執行緒同時訪問賬戶餘額時,會導致最終賬戶餘額不正確。
導致的原因:其中一個執行緒還沒有完成操作時,第二個執行緒就開始訪問賬戶餘額。
解決方案:將多個執行緒之間並行的操作改為序列的操作。
經驗:上述方案會導致程式的執行效率變低,因此能不用則不用。

2.3 實現方式
在Java語言中使用synchronized關鍵字來實現同步鎖機制,從而保證操作的原子性。
具體實現方式有兩種:
a.使用同步語句塊來實現同步鎖機制,語法格式如下:

synchronized(鎖物件的引用){
編寫所有需要鎖定的語句塊;
}
b.使用synchronized關鍵字修飾方法,表示鎖定整個方法的所有方法體。
等價於:

synchronized(this){
編寫所有需要鎖定的語句塊;
}

2.4 死鎖的發生
執行緒一執行的程式碼:
public void run(){

       synchronized(a){      持有物件鎖a,等待物件鎖b
          synchronized(b){
              ... ...
          }
       }
  }           

執行緒二執行的程式碼:

public void run(){
       synchronized(b){      持有物件鎖b,等待物件鎖a
          synchronized(a){
              ... ...
          }
       }
  }           

以後的開發中不要進行同步語句塊的巢狀使用。

2.5 Object類的常用方法
void wait()
- 用於讓當前執行緒進入等待狀態,直到其他執行緒呼叫notify()/notifyAll()方法
void wait(long timeout)
- 用於讓當前執行緒進入等待狀態,直到呼叫上述方法或者引數指定的毫秒到了。
void wait(long timeout, int nanos)
- 用於讓當前執行緒進入等待狀態,直到引數指定的毫秒+納秒到了,或者呼叫方法

void notify() - 用於喚醒等待的單個執行緒(隨機)。
void notifyAll() - 用於喚醒等待的所有執行緒。

視訊
javaseday20-作業講解-01
https://v.qq.com/txp/iframe/player.html?vid=v0798gu669y
javaseday20-Thread類中的常用方法-02
https://v.qq.com/txp/iframe/player.html?vid=t0798ynmazu
javaseday20-同步鎖機制-03
https://v.qq.com/txp/iframe/player.html?vid=z0798xx69qq
javaseday20-生產者和消費者模型-04
https://v.qq.com/txp/iframe/player.html?vid=m0798e2nfw9

程式碼
https://pan.baidu.com/s/1ecwhEd5QoOZpOrI6ztYSmQ

作業:
1.複習和理解執行緒同步機制。
2.參考並編寫學生資訊管理系統的案例。
3.有餘力的同學自己編寫生產者消費者模型的案例。