詳解及對比建立執行緒的三種方式
一.Java建立執行緒的三種方式
Java中建立執行緒主要有三種方式:
1.繼承Thread類
2.實現Runnable介面
3.使用Callable和Future
1.繼承Thead類建立執行緒
(1)繼承Thread類並重寫run方法
(2)建立執行緒物件
(3)呼叫該執行緒物件的start()方法來啟動執行緒
public class CreateThreadTest { public static void main(String[] args) { new ThreadTest().start(); new ThreadTest().start(); } } class ThreadTest extends Thread{ private int i = 0; @Override public void run() { for (; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " is running: " + i); } } }
2.實現Runnable介面建立執行緒
(1)定義一個類實現Runnable介面,並重寫該介面的run()方法
(2)建立 Runnable實現類的物件,作為建立Thread物件的target引數,此Thread物件才是真正的執行緒物件
(3)呼叫執行緒物件的start()方法來啟動執行緒
public class CreateThreadTest { public static void main(String[] args) { RunnableTest runnableTest = new RunnableTest(); new Thread(runnableTest, "執行緒1").start(); new Thread(runnableTest, "執行緒2").start(); } } class RunnableTest implements Runnable{ private int i = 0; @Override public void run() { for (; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " is running: " + i); } } }
3.使用Callable和Future建立執行緒
和Runnable介面不一樣,Callable介面提供了一個call()方法作為執行緒執行體,call()方法比run()方法功能要強大:call()方法可以有返回值,可以宣告丟擲異常。
public interface Callable<V> { V call() throws Exception; }
Java5提供了Future介面來接收Callable介面中call()方法的返回值。 Callable介面是 Java5 新增的介面,不是Runnable介面的子介面,所以Callable物件不能直接作為Thread物件的target。針對這個問題,引入了RunnableFuture介面,RunnableFuture介面是Runnable介面和Future介面的子介面,可以作為Thread物件的target 。同時,Java5提供了一個RunnableFuture介面的實現類:FutureTask ,FutureTask可以作為Thread物件的target。
介紹了相關概念之後,使用Callable和Future建立執行緒的步驟如下:(1)定義一個類實現Callable介面,並重寫call()方法,該call()方法將作為執行緒執行體,並且有返回值
(2)建立Callable實現類的例項,使用FutureTask類來包裝Callable物件
(3)使用FutureTask物件作為Thread物件的target建立並啟動執行緒
(4)呼叫FutureTask物件的get()方法來獲得子執行緒執行結束後的返回值
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class CreateThreadTest { public static void main(String[] args) { CallableTest callableTest = new CallableTest(); FutureTask<Integer> futureTask = new FutureTask<>(callableTest); new Thread(futureTask).start(); try { System.out.println("子執行緒的返回值: " + futureTask.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } } class CallableTest implements Callable{ @Override public Integer call() throws Exception { int sum = 0; for (int i = 1; i < 101; i++) { sum += i; } System.out.println(Thread.currentThread().getName() + " is running: " + sum); return sum; } }
二.建立執行緒的三種方式的對比
1.實現Runnable/Callable介面相比繼承Thread類的優勢
(1)適合多個執行緒進行資源共享
(2)可以避免java中單繼承的限制
(3)增加程式的健壯性,程式碼和資料獨立
(4)執行緒池只能放入Runable或Callable介面實現類,不能直接放入繼承Thread的類
2.Callable和Runnable的區別
(1) Callable重寫的是call()方法,Runnable重寫的方法是run()方法
(2) call()方法執行後可以有返回值,run()方法沒有返回值
(3) call()方法可以丟擲異常,run()方法不可以
(4) 執行Callable任務可以拿到一個Future物件,表示非同步計算的結果 。通過Future物件可以瞭解任務執行情況,可取消任務的執行,還可獲取執行結果
感謝你讀完了這篇文章
我是小架,我們
中秋節後見,祝