接着來討論java中多線程問題。
先說一個問題: 現在有兩個線程,怎麼樣才能讓一個線程執行結束之後再執行另一個線程。
其實只要講要先執行的線程設置爲加入線程就行了。-->join()
這裏寫一下怎麼來實現
假如現在有兩個線程m1和m2,現在要讓m1先執行,也就是講m1設置爲加入線程。要抓一個異常。
try { mt1.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }
關於線程死亡:
public final void stop():直接殺死
public void interrupt():直接殺死,在死前,還可以有遺言
來說一下倆者的區別:
stop是直接將線程殺死
interrupt:線程再被殺死後,會把後邊的代碼執行完,然後再死亡,就是我們說的留遺言。
線程的生命週期(畫圖講解),面試題
1.新建
2.就緒
3.運行
4.有可能阻塞
5.死亡
生命週期圖解如上圖
這裏來一個案例
案例:以給學生設置和獲取姓名和年齡爲例,演示線程通信問題
線程間通訊:
資源:Student
設置數據線程:SetThread
獲取數據線程:GetThread
測試類:StudentDemo
問題1:控制檯出現的結果是:null---0
設置和獲取線程使用的學生資源不是同一個。
如何解決這個問題呢?
把資源作爲構造參數傳遞即可。
問題2:產生了2個問題
相同的數據出現了多次
CPU的一點點時間片就足夠我們的程序執行很多次
數據出現了問題(數據安全問題)
是否是多線程環境
是
是否有共享數據
是
是否有多條語句操作共享數據
是
既然我們知道它是出現了數據安全問題,我們就應該來解決它。
如何解決呢?加鎖
問題3:加了鎖以後,數據還是有問題
多個線程都要加鎖
多個線程加的鎖必須是同一把鎖
以上問題是這個程序中輝徐導的問題,也是必須要解決的。通過這個案例,我們對多線程應該會有一個更爲系統,更爲全面的認識。
大家可以自己去實現,代碼詳見第十六天資料 com.edu_04
關於線程池
程序啓動一個新線程成本是比較高的,因爲它涉及到要與操作系統進行交互。而使用線程池可以很好的提高性能,尤其是當程序中要創建大量生存期很短的線程時,更應該考慮使用線程池。
線程池的特點:
線程池裏的每一個線程代碼結束後,並不會死亡,而是再次回到線程池中成爲空閒狀態,等待下一個對象來使用。
在JDK5之前,我們必須手動實現自己的線程池,從JDK5開始,Java內置支持線程池
線程池的創建機操作
//提交給線程池兩個任務, ExecutorService pool = Executors.newFixedThreadPool(2); //創建任務 MyRunnbale my1 = new MyRunnbale(); MyRunnbale my2 = new MyRunnbale(); //3.提交任務 pool.submit(my1); pool.submit(my2); //關閉線程池 //void shutdown() pool.shutdown();
另外在run方法中寫入要運行的代碼就好了。 這裏線程池的創建的方法要記住,他不同於new對象,是調一個工廠類方法。
java中多線程方面就已經結束了,來簡單總結一下,並說說該注意的。
線程的實現有兩種方法,繼承Thread類或者實現runnable接口。一般推薦使用實現runnable接口這一種方法,因爲他更能體現面向對象的思想,還有一個重要的原因,大家都知道,在java中,支持單繼承多實現,如果用第二種方法,還可以繼承別的類,實現更多的接口。
多線程中會有線程不安全的問題,在編寫代碼的時候要注意解決。
要了解線程的生命週期,理解調用start之後,僅僅只是就緒狀態,只有在搶到cpu放入時間片的時候,才執行。
線程池裏的線程在執行完代碼之後並不會死亡,會自己回到線程池中等待下一個線程對象調用,所以,創建一個含有兩個線程的線程池,並不是只能以操作兩個線程,只要等到一個線程執行完畢,就可以在使用線程池裏的線程。