多線程實現方式(兩種方式的區別)
- 查看源碼的區別:
- a.繼承Thread : 由于子類重寫了Thread類的run(), 當調用start()時, 直接找子類的run()方法
- b.實現Runnable : 構造函數中傳入了Runnable的引用, 成員變量記住了它, start()調用run()方法時內部判斷成員變量Runnable的引用是否為空, 不為空編譯時看的是Runnable的run(),運行時執行的是子類的run()方法
- 繼承Thread
- 好處是:可以直接使用Thread類中的方法,代碼簡單
- 弊端是:如果已經有了父類,就不能用這種方法
- 實現Runnable接口
- 好處是:即使自己定義的線程類有了父類也沒關系,因為有了父類也可以實現接口,而且接口是可以多實現的
- 弊端是:不能直接使用Thread中的方法需要先獲取到線程對象后,才能得到Thread的方法,代碼復雜
還有一種實現方式,就是實現Callable接口,代碼復雜,很少用
多線程同步之Synchronized鎖對象
- 非靜態同步方法的鎖對象是this
- 靜態同步路方法的鎖對象是該類的字節碼對象(XX.class)
- 同步代碼塊的鎖對象不能是匿名對象,因為匿名對象不是同一個對象,其他任意對象都可以
- 在同步代碼塊中,用哪個對象鎖,就用哪個對象調用wait方法
多線程同步之ReentrantLock
- 1.同步
- 使用ReentrantLock類的lock()和unlock()方法進行同步
- 2.通信
- 使用ReentrantLock類的newCondition()方法可以獲取Condition對象
- 需要等待的時候使用Condition的await()方法, 喚醒的時候用signal()方法
- 不同的線程使用不同的Condition, 這樣就能區分喚醒的時候找哪個線程了
sleep(long millis)和wait()區別
- sleep方法必須傳入時間參數,時間到了,自動醒來;wait方法可以傳參也可不傳參數,傳參數表示在參數時間結束后等待,不傳入參數就是直接等待
- sleep方法在同步方法或同步代碼塊中,不釋放鎖(睡著了也要抱著鎖);而wait方法釋放鎖
- sleep是Thread類的靜態方法,而wait方法只能使用鎖對象來調用