Java多執行緒程式設計要點
1、 認識Thread和Runnable
Java中實現多執行緒有兩種途徑:繼承Thread類或者實現Runnable介面。Runnable是介面,建議用介面的方式生成執行緒,因為介面可以實現多繼承,況且Runnable只有一個run方法,很適合繼承。在使用Thread的時候只需繼承Thread,並且new一個例項出來,呼叫 start()方法即可以啟動一個執行緒。
Thread Test = new Thread();
Test.start();
在使用Runnable的時候需要先new一個實現Runnable的例項,之後啟動Thread即可。
Test impelements Runnable;
Test t = new Test();
Thread test = new Thread(t);
test.start();
總結:Thread和Runnable是實現java多執行緒的2種方式,runable是介面,thread是類,建議使用runable實現 java多執行緒,不管如何,最終都需要通過thread.start()來使執行緒處於可執行狀態。
2、 認識Thread的start和run
1) start:
用start方法來啟動執行緒,真正實現了多執行緒執行,這時無需等待run方法體程式碼執行完畢而直接繼續執行下面的程式碼。通過呼叫Thread類的 start()方法來啟動一個執行緒,這時此執行緒處於就緒(可執行)狀態,並沒有執行,一旦得到cpu時間片,就開始執行run()方法,這裡方法 run()稱為執行緒體,它包含了要執行的這個執行緒的內容,Run方法執行結束,此執行緒隨即終止。
2) run:
run()方法只是類的一個普通方法而已,如果直接呼叫Run方法,程式中依然只有主執行緒這一個執行緒,其程式執行路徑還是隻有一條,還是要順序執行,還是要等待run方法體執行完畢後才可繼續執行下面的程式碼,這樣就沒有達到寫執行緒的目的。
總結:呼叫start方法方可啟動執行緒,而run方法只是thread的一個普通方法呼叫,還是在主執行緒裡執行。
3、 執行緒狀態說明
執行緒狀態從大的方面來說,可歸結為:初始狀態、可執行狀態、不可執行狀態和消亡狀態,具體可細分為上圖所示7個狀態,說明如下:
1) 執行緒的實現有兩種方式,一是繼承Thread類,二是實現Runnable介面,但不管怎樣,當我們new了thread例項後,執行緒就進入了初始狀態;
2) 當該物件呼叫了start()方法,就進入可執行狀態;
3) 進入可執行狀態後,當該物件被作業系統選中,獲得CPU時間片就會進入執行狀態;
4) 進入執行狀態後case就比較多,大致有如下情形:
﹒run()方法或main()方法結束後,執行緒就進入終止狀態;
﹒當執行緒呼叫了自身的sleep()方法或其他執行緒的join()方法,就會進入阻塞狀態(該狀態既停止當前執行緒,但並不釋放所佔有的資源)。當 sleep()結束或join()結束後,該執行緒進入可執行狀態,繼續等待OS分配時間片;
﹒當執行緒剛進入可執行狀態(注意,還沒執行),發現將要呼叫的資源被鎖牢(synchroniza,lock),將會立即進入鎖池狀態,等待獲取鎖標記(這時的鎖池裡也許已經有了其他執行緒在等待獲取鎖標記,這時它們處於佇列狀態,既先到先得),一旦執行緒獲得鎖標記後,就轉入可執行狀態,等待OS分配 CPU時間片;
﹒當執行緒呼叫wait()方法後會進入等待佇列(進入這個狀態會釋放所佔有的所有資源,與阻塞狀態不同),進入這個狀態後,是不能自動喚醒的,必須依靠其他執行緒呼叫notify()或notifyAll()方法才能被喚醒(由於notify()只是喚醒一個執行緒,但我們由不能確定具體喚醒的是哪一個執行緒,也許我們需要喚醒的執行緒不能夠被喚醒,因此在實際使用時,一般都用notifyAll()方法,喚醒有所執行緒),執行緒被喚醒後會進入鎖池,等待獲取鎖標記。
﹒當執行緒呼叫stop方法,即可使執行緒進入消亡狀態,但是由於stop方法是不安全的,不鼓勵使用,大家可以通過run方法裡的條件變通實現執行緒的 stop。
4、 Timer 和 Timer Task 的使用
Timer 是一種定時器工具,用來在一個後臺執行緒計劃執行指定任務,這些任務可以被執行一次,也可以被定期執行。每個 Timer 物件對應一個後臺執行緒,順序地執行所有計時器任務。如果完成某個計時器任務的時間太長,那麼它會“獨佔”計時器的任務執行執行緒,從而可能延遲後續任務的執行。對 Timer 物件最後的引用完成並且所有未處理的任務都已執行完成後,計時器的任務執行執行緒會正常終止(並且成為垃圾回收的物件)。TimerTask是一個抽象類,實現了Runable介面,它的子類代表一個可以被Timer計劃的任務。
1) 一個簡單的Demo,讓大家對Timer、TimerTask的使用有感性的認識。
2) Timer和TimerTask的常用api函式說明
這裡強調Timer類的schedule和scheduleAtFixedRate的區別。schedule和 scheduleAtFixedRate的區別在於,schedule以固定的相對時間間隔執行,如果某一次執行被延時了,往後的執行的執行時間也會相對延時;而scheduleAtFixedRate是以絕對的時間間隔執行,如果某一次執行被延時,它的後一次執行的延時將會縮短(scheduleAtFixedRate會把已經過去的時間也作為週期執行)。schedule注重的是時間間隔的穩定,而 scheduleAtFixedRate注重的是執行頻率的穩定。
3) Timer的終止
預設情況下,只要一個程式的timer執行緒在執行,那麼這個程式就會保持執行。當然,你可以通過以下四種方法終止一個timer執行緒:
a)呼叫timer的cancle方法。你可以從程式的任何地方呼叫此方法,甚至在一個timer task的run方法裡;
b)讓timer執行緒成為一個daemon執行緒(可以在建立timer時使用new Timer(true)達到這個目地),這樣當程式只有daemon執行緒的時候,它就會自動終止執行;
c)當timer相關的所有task執行完畢以後,刪除所有此timer物件的引用(置成null),這樣timer執行緒也會終止;
d)呼叫System.exit方法,使整個程式(所有執行緒)終止。
總結:Timer和TimerTask可以簡單理解為Timer定時器在觸發TimerTask任務呼叫,通常用schedule和 scheduleAtFixedRate方法來呼叫timertask任務,cancle來終止任務呼叫。Timer簡單易用,比較適合提供輕量級的計時器功能,但是對時效性很強的任務排程請用其它方法來實現(正如javadoc所述”Timer does not offer real-time guarantees: it schedules tasks using the Object.wait(long) method”)。
4、 callable 實現多執行緒
- import java.util.concurrent.Callable;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.Future;
- /** *//**
- * Callable 和 Future介面
- * Callable是類似於Runnable的介面,實現Callable介面的類和實現Runnable的類都是可被其它執行緒執行的任務。
- * Callable和Runnable有幾點不同:
- * (1)Callable規定的方法是call(),而Runnable規定的方法是run().
- * (2)Callable的任務執行後可返回值,而Runnable的任務是不能返回值的。
- * (3)call()方法可丟擲異常,而run()方法是不能丟擲異常的。
- * (4)執行Callable任務可拿到一個Future物件,
- * Future 表示非同步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,並檢索計算的結果。
- * 通過Future物件可瞭解任務執行情況,可取消任務的執行,還可獲取任務執行的結果。
- */
- public class CallableAndFuture {
- /** *//**
- * 自定義一個任務類,實現Callable介面
- */
- public static class MyCallableClass implements Callable{
- // 標誌位
- private int flag = 0;
- public MyCallableClass(int flag){
- this.flag = flag;
- }
- public String call() throws Exception{
- if (this.flag == 0){
- // 如果flag的值為0,則立即返回
- return "flag = 0";
- }
- if (this.flag == 1){
- // 如果flag的值為1,做一個無限迴圈
- try {
- while (true) {
- System.out.println("looping.");
- Thread.sleep(2000);
- }
- } catch (InterruptedException e) {
- System.out.println("Interrupted");
- }
- return "false";
- } else {
- // falg不為0或者1,則丟擲異常
- throw new Exception("Bad flag value!");
- }
- }
- }
- public static void main(String[] args) {
- // 定義3個Callable型別的任務
- MyCallableClass task1 = new MyCallableClass(0);
- MyCallableClass task2 = new MyCallableClass(1);
- MyCallableClass task3 = new MyCallableClass(2);
- // 建立一個執行任務的服務
- ExecutorService es = Executors.newFixedThreadPool(3);
- try {
- // 提交併執行任務,任務啟動時返回了一個 Future物件,
- // 如果想得到任務執行的結果或者是異常可對這個Future物件進行操作
- Future future1 = es.submit(task1);
- // 獲得第一個任務的結果,如果呼叫get方法,當前執行緒會等待任務執行完畢後才往下執行
- System.out.println("task1: " + future1.get());
- Future future2 = es.submit(task2);
- // 等待5秒後,再停止第二個任務。因為第二個任務進行的是無限迴圈
- Thread.sleep(5000);
- System.out.println("task2 cancel: " + future2.cancel(true));
- // 獲取第三個任務的輸出,因為執行第三個任務會引起異常
- // 所以下面的語句將引起異常的丟擲
- Future future3 = es.submit(task3);
- System.out.println("task3: " + future3.get());
- } catch (Exception e){
- System.out.println(e.toString());
- }
- // 停止任務執行服務
- es.shutdownNow();
- }
- }
相關文章
- Java多執行緒程式設計—鎖優化Java執行緒程式設計優化
- 使用Java實現多執行緒程式設計Java執行緒程式設計
- Java-基礎程式設計-多執行緒Java程式設計執行緒
- python 多執行緒程式設計Python執行緒程式設計
- JavaScript多執行緒程式設計JavaScript執行緒程式設計
- Python多執行緒程式設計Python執行緒程式設計
- Java多執行緒程式設計筆記9:ReentrantReadWriteLockJava執行緒程式設計筆記
- java多執行緒程式設計chap1-2Java執行緒程式設計
- java多執行緒程式設計chap3-4Java執行緒程式設計
- java多執行緒程式設計chap5-7Java執行緒程式設計
- java多執行緒程式設計:你真的瞭解執行緒中斷嗎?Java執行緒程式設計
- Java實驗五: Java多執行緒程式設計(頭歌)Java執行緒程式設計
- 好程式設計師Java培訓分享Java多執行緒程式設計師Java執行緒
- [短文速讀 -5] 多執行緒程式設計引子:程式、執行緒、執行緒安全執行緒程式設計
- 多執行緒程式設計ExecutorService用法執行緒程式設計
- 29. 多執行緒程式設計執行緒程式設計
- Java併發程式設計:Java執行緒Java程式設計執行緒
- 多執行緒程式設計基礎(一)-- 執行緒的使用執行緒程式設計
- 實驗六 Java多執行緒設計Java執行緒
- 多執行緒程式設計總結:一、認識多執行緒本質執行緒程式設計
- JAVA重點類 多執行緒Java執行緒
- Java多執行緒程式設計筆記2:synchronized同步方法Java執行緒程式設計筆記synchronized
- Java多執行緒程式設計筆記10:單例模式Java執行緒程式設計筆記單例模式
- Java多執行緒程式設計基礎知識彙總Java執行緒程式設計
- 深入理解多執行緒程式設計執行緒程式設計
- [02] 多執行緒邏輯程式設計執行緒程式設計
- Linux C++ 多執行緒程式設計LinuxC++執行緒程式設計
- iOS開發-多執行緒程式設計iOS執行緒程式設計
- Task+ConcurrentQueue多執行緒程式設計執行緒程式設計
- C#多執行緒程式設計實戰1.1建立執行緒C#執行緒程式設計
- 多執行緒程式設計基礎(二)-- 執行緒池的使用執行緒程式設計
- C#多執行緒程式設計-基元執行緒同步構造C#執行緒程式設計
- 好程式設計師Java培訓分享Java多執行緒併發程式設計師Java執行緒
- Java基礎之多執行緒程式設計Java執行緒程式設計
- java併發程式設計——執行緒池Java程式設計執行緒
- java併發程式設計——執行緒同步Java程式設計執行緒
- Java併發程式設計之執行緒安全、執行緒通訊Java程式設計執行緒
- 程式設計體系結構(05):Java多執行緒併發程式設計Java執行緒
- Java中的多執行緒程式設計(超詳細總結)Java執行緒程式設計