《多執行緒程式設計》學習之八:方法join()的使用、類ThreadLocal的使用
一、join()方法的使用
一般主執行緒用於建立與啟動子執行緒,如果子執行緒的run()方法耗時比較長,主執行緒常先於子執行緒結束。如果需要主執行緒等待子執行緒執行完畢後再結束,就要用到join()方法。
1.1)子執行緒執行時間不確定,主執行緒中沒法用sleep(?)方法去等待它執行完畢。
1.2)使用join()方法解決:
join()方法使當前執行緒阻塞,直至join()所屬的執行緒物件的run()方法執行完畢才繼續往下執行。
1.3)join()方法與異常
join()方法內部使用的是wait()方法進行等待,如果當前執行緒物件被中斷,則當前執行緒物件出現異常。
如果join()方法與interrupt()方法彼此相遇。本例中threadB出現異常。
1.4)join(long)的使用
執行結果是等待了2s。將main()方法中的程式碼改為Thread.sleep(2000),發現執行結果是一樣的。那麼join(2000)與sleep(2000)究竟有何區別?
1.5)join(long)與sleep(long)的區別
join(long)方法內部使用wait(long)方法實現,具有釋放鎖的特點,而Thread.sleep(long)方法不釋放鎖。
這裡由於執行緒threadB呼叫Thread.sleep(6000)方法,在6s內一直持有threadA物件鎖,所以執行緒threadC只有在6s後才能獲得threadA的鎖,從而呼叫threadA中的同步方法。
如果將Thread.sleep(6000)改為threadA.join(6000),則執行結果如下:
執行緒threadB呼叫threadA.join(6000),此方法會釋放threadA物件鎖,所以執行緒threadC可以呼叫threadA中的同步方法aService();
二、ThreadLocal類的使用
可以使用public static 實現變數的共享,所有的執行緒都是用同一個public static 變數。如要實現每個執行緒都有自己的共享變數的值,則可以使用ThreadLocal類。
1)get()方法和set()方法
可見第一次呼叫test.get()時返回的是null。下面驗證執行緒之間變數的隔離性:
2)執行緒之間變數的隔離性
可見,兩個執行緒都向test物件set()資料,但每個執行緒都可以取出自己的資料。
3)重寫ThreadLocal類的initialValue()方法,使第一次呼叫get()方法時不再返回null。
每個執行緒第一次呼叫ThreadLocal類的get()都會呼叫initialValue()方法,這裡重寫了initialValue()方法,兩個執行緒具有不同的初始值。