您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“Java中線程的創建方式是什么”,內容詳細,步驟清晰,細節處理妥當,希望這篇“Java中線程的創建方式是什么”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
可以通過創建Thread的子類并在子類中重寫run() 方法完成線程創建。示例如下所示。
public class ThreadTest { @Test public void 繼承Thread() throws Exception { // 創建線程對象 MyThread myThread = new MyThread(); // 啟動線程 myThread.start(); // 睡1秒,等待子線程執行完任務 Thread.sleep(1000); } private static class MyThread extends Thread { @Override public void run() { System.out.println("線程執行了"); } } }
運行測試程序,打印如下。
其實可以只繼承Thread,而不重寫run() 方法,此時是不會報錯的,只不過調用start() 方法后線程不會執行任何邏輯。示例如下。
public class ThreadTest { @Test public void 繼承Thread時可以不重寫run方法() { // 創建沒有重寫run()方法的線程對象 MyThreadNotOverrideRun myThread = new MyThreadNotOverrideRun(); // 啟動線程,不報錯,執行的是Thread的run()方法,無任何邏輯 myThread.start(); } private static class MyThreadNotOverrideRun extends Thread {} }
可以通過創建Runnable接口的實現類,然后將Runnable對象作為Thread對象的執行任務,來創建線程。示例如下。
public class ThreadTest { @Test public void 基于Runnable() throws Exception { // 創建Runnable任務對象 Runnable runnable = new Runnable() { @Override public void run() { System.out.println("任務執行"); } }; // 創建Thread對象時將Runnable任務對象通過構造函數傳入 Thread thread = new Thread(runnable); // 啟動線程 thread.start(); // 睡1秒,等待子線程執行完任務 Thread.sleep(1000); } }
運行測試程序,執行結果如下所示。
Callable接口也是可以作為任務被線程執行,其與Runnable接口的區別在于Callable任務可以有返回值,而Runnable任務沒有返回值。
由于Thread對象只能執行Runnable任務,因此無法直接讓Thread執行Callable任務,但是可以先將Callable封裝成FutureTask,而FutureTask是實現了Runnable接口的,所以Thread對象可以執行FutureTask任務。示例如下。
public class ThreadTest { @Test public void 基于Callable() throws Exception { // 創建Callable任務對象 Callable<String> callable = new Callable<String>() { @Override public String call() throws Exception { return "任務執行結果"; } }; // 將Callable封裝成FutureTask FutureTask<String> futureTask = new FutureTask<>(callable); // 創建Thread對象時將FutureTask通過構造函數傳入 Thread thread = new Thread(futureTask); // 啟動線程 thread.start(); // 通過FutureTask拿到執行結果 System.out.println(futureTask.get()); } }
運行測試程序,結果如下。
在第三小節中是基于Callable來創建的FutureTask,本小節將基于Runnable來創建FutureTask。在此之前,先看一下FutureTask的類圖,如下所示。
所以FutureTask即能夠作為Runnable被執行,也能夠作為Future獲取異步執行的結果。FutureTask有兩個構造函數,簽名如下。
// 基于Callable創建FutureTask public FutureTask(Callable<V> callable) // 基于Runnable創建FutureTask public FutureTask(Runnable runnable, V result)
下面重點看一下如何基于Runnable創建FutureTask,源碼如下所示。
public FutureTask(Runnable runnable, V result) { // 使用Executors工具類將Runnable封裝成Callable this.callable = Executors.callable(runnable, result); this.state = NEW; }
繼續看Executors#callable(java.lang.Runnable, T) 方法,如下所示。
public static <T> Callable<T> callable(Runnable task, T result) { if (task == null) { throw new NullPointerException(); } // 將Runnable封裝成RunnableAdapter return new RunnableAdapter<T>(task, result); }
那么Executors#callable(java.lang.Runnable, T) 方法中就是將Runnable封裝成了RunnableAdapter,最后再看一下RunnableAdapter的實現。
static final class RunnableAdapter<T> implements Callable<T> { final Runnable task; final T result; RunnableAdapter(Runnable task, T result) { this.task = task; this.result = result; } public T call() { // 執行Runnable的邏輯 task.run(); // 執行完畢后,result作為結果返回 return result; } }
所以這里可以知道,基于Runnable
創建FutureTask
,其本質是將Runnable
先封裝為Callable
,然后再將Callable
封裝成FutureTask
。還有一點需要注意,在基于Runnable
創建FutureTask
時,除了傳入Runnable
,還可以傳入一個作為返回結果的對象,Runnable
執行完畢后,會將這個對象返回,這個對象也可以傳一個null,表示不需要返回值。
基于Runnable創建FutureTask的一個示例如下。
public class ThreadTest { @Test public void 基于Runnable來構建FutureTask() throws Exception { // 創建結果對象 MyResult myResult = new MyResult(); // 創建Runnable任務對象 Runnable runnable = new Runnable() { @Override public void run() { myResult.setResult("任務執行"); } }; // 將Runnable封裝成FutureTask // Runnable執行后,會改變MyResult對象 FutureTask<MyResult> futureTask = new FutureTask<>(runnable, myResult); // 創建Thread對象時將FutureTask通過構造函數傳入 Thread thread = new Thread(futureTask); // 啟動線程 thread.start(); // 通過FutureTask拿到執行結果 System.out.println(futureTask.get().getResult()); } private static class MyResult { String result; public MyResult() {} public MyResult(String result) { this.result = result; } public String getResult() { return result; } public void setResult(String result) { this.result = result; } } }
運行測試程序,結果如下所示。
讀到這里,這篇“Java中線程的創建方式是什么”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。