如何建立執行緒
阿新 • • 發佈:2020-07-12
執行緒建立
目錄
一. 執行緒建立的方式
Ⅰ. 繼承Thread類
- 自定義一個類,繼承Thread類
- 重寫run方法,run方法中用於定義當前執行緒的執行邏輯。
- 建立執行緒類的物件
- 開啟執行緒 Thread類中start()方法啟動執行緒
/** * 此案例展示第一種建立執行緒之方法:繼承Thread類 * 說明: * 1.若 static 修飾 i,則共享i * * 關於Thread中的幾個方法: * 1.雖然main()也是一個執行緒,但若需要Thread中的函式,如yiled()或sleep() * 也需要繼承Thread,其本身不具有。 * 2.線上程執行體中可以直接使用Thread中的方法如getName(),但main()中 * 需要先返回當前執行緒物件。 * 3.getName()是Thread類中的方法,若只是實現了Runnable介面,也需要先返回 * 當前執行緒物件才能使用 * 4.sleep() yiled()是Thread中的靜態方法 */ public class FirstThread extends Thread { private int i; @Override public void run() { //繼承了getName() for (;i<100; i++) { System.out.println(getName() + " " + i); } } public static void main(String[] args) throws InterruptedException { for(int i = 0;i<100;i++){ System.out.println(Thread.currentThread().getName()+" "+i); if(i==20){ new FirstThread().start(); new FirstThread().start(); //yield(); sleep(1000); } } } }
Ⅱ. 實現Runnable介面
- 自定義一個類 實現Runnable介面。
- 實現run方法。
- 建立一個自定義執行緒類的物件,但是該物件身上沒有start啟動執行緒的方法;可以建立Thread物件,將自定義執行緒類的物件作為引數傳入構造方法中。
- 呼叫start方法啟動執行緒
/** * 此案例展示建立執行緒的第二種方法:實現Runnable介面 * 其實現類僅作為Thread類的target。(把run()包裝成一個Thread類) * * 說明:此方法中雖然new了兩個類物件,但都作為了一個Thread類的target * 所以共享了變數i * */ public class SecendThread implements Runnable { private int i; @Override public void run() { for(;i<100;i++){ System.out.println(Thread.currentThread().getName()+" "+i); } } public static void main(String[] args) { for(int i = 0;i<100;i++){ System.out.println(Thread.currentThread().getName()+" "+i); if(i==20){ SecendThread secendThread = new SecendThread(); new Thread(secendThread,"執行緒一").start(); new Thread(secendThread,"執行緒二").start(); } } } }
Ⅲ. 實現Runnable介面
- 自定義一個類 實現Callable介面
- 實現call方法 call方法中包含的是執行緒執行邏輯程式碼
- Executors獲取執行緒服務物件
- 呼叫執行緒服務物件submit,將自定義執行緒物件傳給submit方法的引數;submit返回值為Future型別,call方法的返回值就包含在Future物件中;可以通過future的get方法獲取返回值物件
public class ThreadDemo2 { public static void main(String[] args) throws Exception { //獲取執行緒池的服務 物件 ExecutorService service = Executors.newCachedThreadPool(); MyThread2 myThread2 = new MyThread2(); //通過submit方法來執行執行緒 Future future = service.submit(myThread2); //Future中包含了執行緒的返回值 Object o = future.get(); System.out.println(o); } } //自定義執行緒--方式三 class MyThread2 implements Callable{ @Override public Object call() throws Exception { System.out.println("通過實現Callable介面自定義執行緒~~"); return "hello"; } }
三. 對比總結
-
只有方法一需要繼承Thread類,不如後兩者。
-
只有方法三可以有返回值,可以丟擲異常。
-
Callable通過泛型來定義返回結果型別。在實際開發過程中和Runnable相似,如果需要執行結果那麼使用Callable。
Runnable Callable 返回值 沒有 通過泛型來定義返回值型別 啟動方式 1.通過Thread直接啟動
2.通過執行緒池的execute或者submit方法啟動1.通過FutureTask轉化成Runnable之後再通過Thread啟動
2.通過執行緒池的submit方法啟動⭐️異常處理 1.不允許拋異常,那麼就無法通過全域性方法來處理。 允許拋異常,能通過全域性方式來統一處理。