十四、執行緒
1.什麼是程序?什麼是執行緒?
程序是一個應用程式(一個程序一個軟體)
執行緒是一個程序中的執行場景/執行單元
一個程序可以啟動多個執行緒
2.對於java來說,啟動JVM,JVM在啟動一個主執行緒呼叫main方法,同時再啟動一個垃圾回收器執行緒負責看護,回收垃圾。
3.程序與執行緒的關係?
程序與程序之間記憶體獨立不共享。
執行緒與執行緒之間在java語言中:
堆記憶體和方法去記憶體共享。
棧記憶體獨立,一個執行緒一個棧。
4.多執行緒機制可以提高程式處理效率。
5.使用對執行緒機制之後,main方法結束,程式可能不會結束。main方法結束,只是主棧空了,其他棧(執行緒)可能還在壓棧彈棧。
6.JVM虛擬機器:
方法區、堆記憶體只有一個。多執行緒共享 。
一個棧一個執行緒。支棧:分支執行緒。
7.什麼是多執行緒併發?
t1執行緒執行t1的,t2執行緒執行t2的。
t1不會影響t2,t2不會影響t1。這才叫多執行緒併發。
8.對於一個單核的CPU來說,真的可以做到多執行緒併發嗎?
對於多核的CPU電腦,真正的多執行緒併發是沒有問題的。
單核的CPU表示只有一個大腦:
不能夠做到真正的多執行緒併發,但是可以給人一種”多執行緒併發“的感覺。對於單核的CPU來說,在某一個時間點上實際上只能處理一件事情,但是由於CPU執行速度處理極快,多個執行緒之間頻繁切換執行,給人的感覺就是同時在做。
9.實現執行緒的方式:
java支援多執行緒機制,並且java已經將多執行緒實現了,我們只需要繼承就行。
第一種:編寫一個類,直接繼承java.lang.Thread,重寫run方法。
怎麼建立執行緒物件? new就行了
怎麼啟動執行緒? 呼叫執行緒物件的start()方法。
public class Test{ public static void main(String[] args) { //主執行緒在主棧中 //建立分支執行緒物件 MyThread th = new MyThread();View Code//啟動執行緒 th.start(); //start()方法的作用:啟動一個分支執行緒,在JVM中開闢一個新的棧空間, //這段程式碼任務完成之後,瞬間就結束了。 //這段程式碼的任務只是為了開啟一個新的棧空間,只要新的棧空間開出來, //start()方法就結束了。執行緒就啟動成功了。 //啟動成功的執行緒會自動呼叫run()方法並且run()方法在分支線的棧底部(壓棧)。 //run方法在分支執行緒的底部,main方法在主棧的棧底部,run和main是平級的。 //直接呼叫run方法,與呼叫start的方法有啥區別? //th.run();//不會啟動執行緒,不會分配新的分支棧。(等於在同一個棧中,單執行緒) //這裡的程式碼還是執行在主執行緒中 for(int i = 0; i < 100;i++) { System.out.println("main"); } } }
以上程式碼輸出結果有這樣的特點:有先有後。有多有少。Why?
某個執行緒搶到執行權。
第二種實現執行緒方式:編寫一個類實現java.lang.Runnable介面
推薦介面:面向介面程式設計。一個類實現了介面,它還可以去繼承其它的類,更靈活。
class MyRunable implements Runnable{ @Override public void run() { for(int i = 0; i < 100;i++) { System.out.println("MyRunabale"); } } } public class Test{ public static void main(String[] args) { //建立一個可執行的物件 MyRunable r = new MyRunable(); //將可執行的物件封裝成一個執行緒物件 Thread t = new Thread(r); //合併程式碼 //Thread tt = new Thread(new MyRunable()); //啟動執行緒 t.start(); for(int i = 0; i < 100;i++) { System.out.println("main"); } } }View Code
第三種採用匿名內部類的方法去實現:
public class Test{ public static void main(String[] args) { Thread t = new Thread(new Runnable() { @Override public void run() { for(int i = 0; i < 100;i++) { System.out.println("Runabale"); } } }); //啟動執行緒 t.start(); for(int i = 0; i < 100;i++) { System.out.println("mian"); } } }View Code
10.執行緒生命週期:
新建狀態、就緒狀態、執行狀態、執行狀態、阻塞狀態、死亡狀態
11、關於執行緒的一些操作:
11.1、怎麼獲取執行緒物件?
public static native Thread currentThread()
Thread t = Thread.currentThread();//返回t就是當前執行緒。
11.2、執行緒物件的名字:執行緒物件 .getName()
11.3、修改執行緒物件名字:執行緒物件 .setName("")
11.4、當執行緒沒有設定名字:Thread-0、Thread-1
public class Test{ public static void main(String[] args) { MyRun h = new MyRun(); h.doSome(); System.out.println(); //這個程式碼出現在main中,所以執行緒就是主執行緒。 Thread tt = Thread.currentThread(); System.out.println(tt.getName());//main MyRun t = new MyRun(); //t.setName("t1"); String tName = t.getName(); //預設Thread-0 System.out.println(tName); MyRun t2 = new MyRun(); String tName2 = t2.getName(); //Thread-1 System.out.println(tName2); System.out.println(); t.start(); t2.start(); } }View Code
11.5、關於執行緒sleep()方法:
public static native void sleep(long millis) throws InterruptedException
- 靜態方法
- .引數是毫秒
- 作用:讓【當前執行緒】進入休眠狀態,放棄CPU時間片,讓給其他先程使用。
- 實現:間隔特定時間,去執行一段特定的程式碼.
public class Test{ public static void main(String[] args) { try { Thread.sleep(1000*5); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("HelloWorld"); for(int i = 0;i<10;i++){ System.out.println(Thread.currentThread().getName() + i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }View Code
11.6、終止執行緒的睡眠(不是終斷執行緒的執行)
中斷睡眠的方式依靠了java的異常處理機制java.lang.InterruptedException: sleep interrupted
class MyRun1 implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+ "--> begin"); try { //子類重寫父類不能丟擲比父類更多、更寬的異常 Thread.sleep(1000*60*60); } catch (InterruptedException e) { //列印異常資訊 e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+ "--> end"); } } public class Test{ public static void main(String[] args) { Thread t = new Thread(new MyRun1()); t.setName("t"); t.start(); //希望在5秒後,t執行緒醒來 try { Thread.sleep(1000*5); } catch (InterruptedException e) { e.printStackTrace(); } //終斷t執行緒的睡眠 t.interrupt(); } }View Code
12.關於多執行緒併發環境下,資料的安全問題
12.1、什麼時候資料在多執行緒併發的環境下會存在安全問題呢?
- 多執行緒併發
- 有共享資料
- 共享資料有修改的行為
滿足以上三個條件之後,就會存線上程安全問題。
12.2、怎麼解決執行緒安全問題?
執行緒同步機制:執行緒排隊執行。(不能併發)
會犧牲一部分效率。(安全第一)
12.3、synchronized的三種方法:
第一種:同步程式碼塊
synchronized(執行緒共享物件){
同步程式碼塊;
}
第二種:在例項方法上使用synchronized
表示共享物件一定是this
並且同步程式碼塊是整個方法體。
第三種:在靜態方法上使用synchronized
表示找類鎖。
類鎖永遠只有1把。
JavaSE更新基本結束,後續或許會補充,或許不會。
上一篇:十三、IO流
下一篇:資料結構:持續更新中