Java多線程教程之如何利用Future實現攜帶結果的任務
Future 介紹
Future表示異步計算的結果,它提供瞭檢查計算是否完成的方法,以等待計算的完成,並檢索計算的結果。Future的cancel方法可以取消任務的執行,它有一佈爾參數,參數為 true 表示立即中斷任務的執行,參數為 false 表示允許正在運行的任務運行完成。Future的 get 方法等待計算完成,獲取計算結果。
Runnable
Runnable 是我們多線程開發過程中常用的接口。 Executor 框架使用 Runnable 作為其基本的任務表現形式。 Runnable 是一個有很大局限性的接口,run() 方法沒有返回值並且不能拋出一個受檢查的異常。
@FunctionalInterface public interface Runnable { public abstract void run(); }
Callable
與 Runnable 不同,Callable 是個泛型參數化接口,它能返回線程的執行結果,出錯時可能拋出異常。
多線程future
Future
Executor 執行的任務有 4 個生命周期階段:創建、提交、開始和完成。由於有些任務執行很耗時間,因此有些時候希望能夠取消這些任務。Executor 框架中,已經提交但未開始的任務可以取消,已經開始的任務隻有當它們能響應中斷才能取消,取消已經完成的任務是沒有任何影響。
Future 表示一個任務的生命周期,並提供瞭相應的方法來判斷任務是否已經完成或者取消,以及獲取任務的結果和取消任務。
public interface Future<V> { // 取消任務 boolean cancel(boolean mayInterruptIfRunning); // 判斷是否已經取消 boolean isCancelled(); // 如果任務已經結束返回 true boolean isDone(); // 若有必要會一直阻塞直到結束並返回結果 V get() throws InterruptedException, ExecutionException; // 若有必要會阻塞指定的時間等待結束並返回結果 V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
ExecutorService 中所有的 submit 方法都返回一個 Future 對象,從而將一個 Runnable 或 Callable 提交給 Executor, 可以通過返回的 Future 來取消任務或者獲取返回結果。
還可以顯示地將某個指定的 Runnable 或 Callable 實例化為 FutureTask ,由於 FutureTask 類實現瞭 Runnable、Future 接口,因此可以將它提交給 Executor 來執行。
FutureTask 繼承關系:
public class FutureTask<V> implements RunnableFuture<V> { ...... }
public interface RunnableFuture<V> extends Runnable, Future<V> { void run(); }
Future 和 FutureTask 的一個區別在於,Future 需要通過 ExecutorService 中的 submit 方法的返回值來獲取結果,而 FutureTask 提交任務時不需要設置返回值,通過自身就可以獲取結果。
下面來看一個計算 0~10 之間的整數之和並返回結果的例子:
import java.time.LocalDateTime; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; /** * @author :jhys * @date :Created in 2021/7/6 14:43 * @Description : */ public class FutureTest1 { public static void main(String[] args) throws Exception { ExecutorService executor = Executors.newSingleThreadExecutor(); System.out.println(LocalDateTime.now() + ": thread start"); Future<Integer> future = executor.submit(() -> { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(LocalDateTime.now() + ": task start"); int sum = 0; for (int i = 0; i <= 10; i++) { sum += i; } return sum; }); executor.shutdown(); try { Integer ret = future.get(); System.out.println(LocalDateTime.now() + ": ret = " + ret); } catch (Exception e) { e.printStackTrace(); } System.out.println("finish"); } }
輸出結果:
2021-07-06T14:49:21.244: thread start
2021-07-06T14:49:24.259: task start
2021-07-06T14:49:24.259: ret = 55
finish
將上面的例子中 Future 替換為 FutureTask ,代碼如下:
public class FutureTest { public static void main(String[] args) { FutureTask<Integer> future = new FutureTask<>(() -> { Thread.sleep(3000); System.out.println(LocalDateTime.now() + ": task start"); int sum = 0; for (int i =0; i <= 10; i++) { sum += i; } return sum; }); ExecutorService executor = Executors.newSingleThreadExecutor(); // 註意這裡的區別,不需要顯示獲取返回值 executor.submit(future); executor.shutdown(); try { System.out.println(LocalDateTime.now() + ": ret = " + future.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println("finish"); } }
總結
到此這篇關於Java多線程教程之如何利用Future實現攜帶結果任務的文章就介紹到這瞭,更多相關Java多線程Future實現帶結果任務內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet
推薦閱讀:
- Java並發工具類Future使用示例
- Java多線程 Callable、Future 和FutureTask
- Java多線程之FutureTask的介紹及使用
- 解析Java異步之call future
- Java並發編程必備之Future機制