案例
例如:今天是小妹的生日,需要一個蛋糕有點儀式感,于是去蛋糕店預定,預定完之后,店老板說蛋糕做好了,到時電話通知你,不可能在這傻傻的等著吧,還有其他事情要做啊,于是我的去做其他事情,等老板電話后再來取蛋糕。這樣可以充分利用自己的時間去賺錢,如果用這個案例寫一個Java代碼 如何實現,
Future的理解和用途
Future是個未來的事情,相當與一個票據,或者可以理解是一個憑證,用這個憑證去獲取所需要的結果,
代碼的邏輯解析
SimpleFuture —>代表未來的一個憑據
SimpleFutureTask —>將你的調用邏輯進行隔離封裝
SimpleFutureService —> 橋接Future和FutureTask
這是一種很好的設計模式 SimpleFuture 不需要知道 SimpleFutureTask的存在,而SimpleFutureTask也不需要知道SimpleFuture 的存在,只要SimpleFutureService 需要知道他們兩者的存在,而對于調用者而言,只要知道SimpleFutureService 就行,我們將業務邏輯封裝成一個task模式,并且返回一個SimpleFuture
簡單的Future憑證接口
1、get方法
獲取任務結束后返回的結果,如果調用時,任務還沒有結束,則會進行阻塞線程,直到任務完成。該阻塞是可以被打斷的,打斷的線程是調用get方法的線程,被打斷后原任務會依舊繼續執行。
/*** SimpleFuture接口定義了一個簡單的異步計算的結果獲取方法* 它提供了一種機制來獲取異步任務的結果,如果任務尚未完成,則調用get方法的線程會被阻塞,* 直到計算完成并且結果可用* * @param <T> 表示異步計算結果的類型*/
public interface SimpleFuture<T> {/*** 獲取異步計算的結果如果計算尚未完成,則此方法會阻塞,直到計算完成* 如果計算過程中遇到中斷,此方法會拋出InterruptedException* * @return 異步計算的結果* @throws InterruptedException 如果調用get方法的線程在等待計算完成時被中斷*/T get() throws InterruptedException;
}
獲取任務的結果
/*** SimpleFutureTask接口定義了一個異步任務的標準.* 它代表了一個將會在將來執行的任務,并且該任務有一個結果.* 這個接口的主要用途是為那些想要實現異步執行并返回結果的任務提供一個統一的標準.** @param <T> 表示任務返回結果的類型.*/
public interface SimpleFutureTask<T> {/*** 執行異步任務并返回結果.* 該方法將在某個時刻被調用,以期望異步地完成任務并返回結果.* * @return 任務的結果,類型為泛型T.*/T call();
}
實現SimpleFuture的接口
/*** AsynSimpleFuture 類實現了一個異步操作的簡單未來對象* 它允許在一個線程中設置結果,在另一個線程中獲取結果* 主要用于線程間通信,以異步方式處理任務的結果** @param <T> 未來操作結果的類型*/
public class AsynSimpleFuture<T> implements SimpleFuture<T>{// 標記任務是否完成,volatile 關鍵字確保多線程環境下的可見性private volatile boolean finished = false;// 存儲任務的結果private T result;/*** 當任務完成時調用此方法,它會設置結果值并通知所有等待的線程** @param result 任務的結果*/public void finish(T result){synchronized (this){this.result = result;this.finished = true;this.notifyAll();}}/*** 獲取任務的結果如果任務未完成,當前線程會等待直到任務完成** @return 任務的結果* @throws InterruptedException 如果在等待過程中線程被中斷*/@Overridepublic T get() throws InterruptedException {synchronized (this){while (!finished){this.wait();}}return result;}
}
將SimpleFutureTask和 SimpleFutureTask 或 AsynSimpleFuture聯系起來
/*** SimpleFutureService類提供了異步執行任務的功能* 它通過管理線程來執行提交的任務,并返回一個表示異步計算結果的AsynSimpleFuture對象*/
public class SimpleFutureService {/*** 提交一個SimpleFutureTask任務進行異步執行* 該方法的返回值可以為 SimpleFuture<T>* @param task 要異步執行的任務,它實現了call方法來定義任務的具體執行邏輯* @return 返回一個AsynSimpleFuture對象,通過它可以獲取任務執行結果* * 此方法創建并啟動一個新的線程來執行給定的任務任務的執行結果會被封裝在這個AsynSimpleFuture對象中* 使用者可以使用這個對象來獲取任務執行結果,而無需阻塞當前線程*/public <T> AsynSimpleFuture<T> submit(SimpleFutureTask<T> task, Consumer<T> consumer) {AsynSimpleFuture<T> future = new AsynSimpleFuture<>();new Thread(() -> {T result = task.call();future.finish(result);consumer.accept(result);}).start();return future;}
}
測試一下代碼的效果
/*** SyncInvoker 類用于演示如何使用 SimpleFutureService 來執行異步任務并在任務完成后獲取結果*/
public class SyncInvoker {/*** 主函數執行異步任務并展示執行結果* @param args 命令行參數* @throws InterruptedException 如果在睡眠期間線程被中斷*/public static void main(String[] args) throws InterruptedException {// 創建 SimpleFutureService 實例SimpleFutureService simpleFutureService = new SimpleFutureService();// 提交異步任務并獲取未來結果simpleFutureService.submit(SyncInvoker::bookAndPickUpCake,System.out::println);Optional.of("-----*************-------").ifPresent(System.out::println);// 應該是在獲取結果之前,先執行其他任務Optional.of("-----go to work-------").ifPresent(System.out::println);// 模擬其他任務的耗時Thread.sleep(5000);Optional.of("-----I finish my work -------").ifPresent(System.out::println);Optional.of("-----####去蛋糕店等待或等待老板電話或老板送貨上面#####-------").ifPresent(System.out::println);}/*** 模擬一個耗時的異步任務,例如預訂并取回蛋糕* @return 任務結果,在這個例子中是蛋糕的名稱*/private static String bookAndPickUpCake() {try {// 模擬耗時操作Thread.sleep(10000);return "BIRTHDAY CAKE";} catch (InterruptedException e) {throw new RuntimeException(e);}}
}執行的結果:
-----*************-------
-----go to work-------
-----I finish my work -------
-----####等待老板電話或老板送貨上面#####-------
BIRTHDAY CAKE