執行緒&同步習題答案
基礎題
練習一:多執行緒開啟
問題:
請描述Thread類中的start()方法與run()方法的區別。
答:
執行緒物件呼叫run()方法不開啟執行緒,僅是物件呼叫方法。執行緒物件呼叫start()方法開啟執行緒,並讓jvm呼叫run()方法在開啟的執行緒中執行。
練習二:建立多執行緒
問題:
請描述建立執行緒的兩種方式。
答:
第一種方式是將類宣告為 Thread 的子類。
- 定義Thread類的子類,並重寫該類的run()方法,該run()方法的方法體就代表了執行緒需要完成的任務,因此把run()方法稱為執行緒執行體。
- 建立Thread子類的例項,即建立了執行緒物件。
- 呼叫執行緒物件的
第二種方式是宣告一個類實現Runnable 介面。
1. 定義Runnable介面的實現類,並重寫該介面的run()方法,該run()方法的方法體同樣是該執行緒的執行緒執行體。
2. 建立Runnable實現類的例項,並以此例項作為Thread的target來建立Thread物件,Thread物件才是真正的執行緒物件。
3. 呼叫執行緒物件的start()方法來啟動執行緒。
練習三:多執行緒練習
問題:
請編寫程式,分別列印主執行緒的名稱和子執行緒的名稱。
要求使用兩種方式實現:
第一種方式:繼承Thread類。
第二種方法:實現Runnable介面。
答:
操作步驟描述
第一種方式:繼承Thread類
1.定義一個子執行緒的類,繼承Thread類;
2.在子執行緒類中重寫run方法,在run方法中列印子執行緒的名稱;
3.定義一個測試類;
4.在main方法中列印主執行緒的名稱;
5.在main方法中建立子執行緒物件;
6.呼叫子執行緒物件的start方法,開啟子執行緒;
第二種方式:實現Runnable介面
1.定義一個子任務類,實現Runnable介面;
2.在子任務類中重寫run方法,在run方法中列印子執行緒的名稱;
3.定義一個測試類;
4.在main方法中列印主執行緒的名稱;
5.在main方法中建立一個子任務物件;
6.在main方法中建立一個Thread類的物件,並把子任務物件傳遞給Thread類的構造方法;
7.呼叫Thread類物件的start方法開啟子執行緒;
操作步驟答案
l第一種方式:繼承Thread類
/*
* 1.定義一個子執行緒的類,繼承Thread類;
*/
public class SubThread extends Thread { /* *2.在子執行緒類中重寫run方法,在run方法中列印子執行緒的名稱; */ public void run() { // 列印子執行緒的名稱 System.out.println("subThread:" + Thread.currentThread().getName()); } }
/*
* 3.定義一個測試類
*/
public class ThreadDemo { public static void main(String[] args) { // 4.在main方法中列印主執行緒的名稱; System.out.println("main:" + Thread.currentThread().getName()); // 5.在main方法中建立子執行緒物件; SubThread st = new SubThread(); // 6.呼叫子執行緒物件的start方法,開啟子執行緒。 st.start(); } }
第二種方式:實現Runnable介面
/*
* 1.定義一個子任務類,實現Runnable介面。
*/
public class SubRunnable implements Runnable { @Override public void run() { // 2.在子任務類中重寫run方法,在run方法中列印子執行緒的名稱。 System.out.println("SubRunnable:"+ Thread.currentThread().getName()); } }
/*
* 3.定義一個測試類。
*/
public class RunnableDemo { public static void main(String[] args) { // 4.在main方法中列印主執行緒的名稱。 System.out.println("RunnableDemo:"+ Thread.currentThread().getName()); // 5.在main方法中建立一個子任務物件。 SubRunnable r = new SubRunnable(); // 6.在main方法中建立一個Thread類的物件,並把子任務物件傳遞給Thread類的 構造方法。 Thread t = new Thread(r); // 7.呼叫Thread類物件的start方法開啟子執行緒。 t.start(); } }
練習四:實現Runnable介面的優勢
問題:
請描述實現Runnable介面比繼承Thread類所具有的優勢:
答:
1. 適合多個相同的程式程式碼的執行緒去共享同一個資源。
2. 可以避免java中的單繼承的侷限性。
3. 增加程式的健壯性,實現解耦操作,程式碼可以被多個執行緒共享,程式碼和資料獨立。
4. 執行緒池只能放入實現Runable或callable類執行緒,不能直接放入繼承Thread的類。
練習五:執行緒狀態
問題:請描述線上程的生命週期中, 有幾種狀態呢?
答:
- NEW(新建) 執行緒剛被建立,但是並未啟動。
- Runnable(可執行)
執行緒可以在java虛擬機器中執行的狀態,可能正在執行自己程式碼,也可能沒有,這取決於作業系統處理器。
- Blocked(鎖阻塞)
當一個執行緒試圖獲取一個物件鎖,而該物件鎖被其他的執行緒持有,則該執行緒進入Blocked狀態;當該執行緒持有鎖時,該執行緒將變成Runnable狀態。
- Waiting(無限等待)
一個執行緒在等待另一個執行緒執行一個(喚醒)動作時,該執行緒進入Waiting狀態。進入這個狀態後是不能自動喚醒的,必須等待另一個執行緒呼叫notify或者notifyAll方法才能夠喚醒。
- Timed Waiting(計時等待)
同waiting狀態,有幾個方法有超時引數,呼叫他們將進入Timed Waiting狀態。這一狀態將一直保持到超時期滿或者接收到喚醒通知。帶有超時引數的常用方法有Thread.sleep 、Object.wait。
- Teminated(被終止)
因為run方法正常退出而死亡,或者因為沒有捕獲的異常終止了run方法而死亡。