Java使用FutureTask實現預加載的示例詳解
FutureTask介紹
FutureTask也可以用作閉鎖;FutureTask的計算是通過Callable來實現的,相當于一種可生成結果的Runnable,并且可以處于3種狀態(tài),分別是等待運行(waiting to run)
、正在運行(Running)
、和運行完成(Completed)
,而運行完成
表示計算的所有可能結束方式,包括正常結束
,由于取消而結束
和由于異常而結束
等,當FutureTask進入完成狀態(tài)后,它就會永遠停止在這個狀態(tài)上。我們可以使用Future.get()
方法獲取任務執(zhí)行的狀態(tài)。
使用場景
Future.get的行為取決于任務的狀態(tài),如果任務已經完成,那么get會立即返回結果,否則get方法將阻塞直到任務進入完成狀態(tài),然后返回結果或者拋出異常,FutureTask將計算結果從執(zhí)行計算的線程傳遞到獲取這個結果的線程,而FutureTask的規(guī)范確保了這種傳遞過程能實現結果的正確性
基于FutureTask的特性,通??梢允褂肍utureTask做一些預加載工作,比如一些時間較長的計算,這些計算可以在使用計算結果之前啟動,并且計算的結果將在稍后是同,通過提前啟動計算,可以減少等待結果時需要的時間
實例解析
假設我們要加載一個產品信息,使用FutureTask來執(zhí)行一個高開銷的計算。代碼如下所示: 首先簡單寫一個產品的Bean類:
static class ProductInfo { public ProductInfo(String name, String order_id) { this.name = name; this.order_id = order_id; } private String name; private String order_id; @Override public String toString() { return "ProductInfo{" + "name='" + name + '\'' + ", order_id='" + order_id + '\'' + '}'; } }
然后使用FutureTask實現一個產品信息預加載功能:
static class Preloader { public void start() { thread.start(); } private final FutureTask<ProductInfo> futureTask = new FutureTask<>(new Callable<ProductInfo>() { @Override public ProductInfo call() throws Exception { return loadProductInfo(); } }); public ProductInfo get() throws ExecutionException, InterruptedException { return futureTask.get(); } private final Thread thread = new Thread(futureTask); private ProductInfo loadProductInfo() { try { Thread.sleep(5000); } catch (InterruptedException e) { throw new RuntimeException(e); } return new ProductInfo("衣服", "9527"); } }
驗證代碼:
Preloader preloader = new Preloader(); preloader.start(); System.out.println("start get product info before" + System.currentTimeMillis() / 1000); ProductInfo productInfo = null; try { productInfo = preloader.get(); } catch (ExecutionException | InterruptedException e) { throw new RuntimeException(e); } System.out.println("start get product info afte" +System.currentTimeMillis() / 1000); System.out.println("productInfo: " + productInfo);
如上面的代碼所示:Preloader
創(chuàng)建了一個FutureTask,其中包含了加載產品信息的任務,以及一個執(zhí)行運算的線程。我們增加了一個 Thread.sleep(5000);
模擬加載耗時。由于在構造函數或者靜態(tài)初始化方法中啟動線程不是一種好方法,所以提供了一個start方法來啟動線程,當程序后面需要ProductInfo
結果時,可以調用Preloader
提供的get
方法,如果數據已經加載,那么會返回這些數據,否則將等待加載完成后再返回。
到此這篇關于Java使用FutureTask實現預加載的示例詳解的文章就介紹到這了,更多相關Java FutureTask預加載內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring Data JPA的Audit功能審計數據庫的變更
數據庫審計是指當數據庫有記錄變更時,可以記錄數據庫的變更時間和變更人等,這樣以后出問題回溯問責也比較方便,本文討論Spring Data JPA審計數據庫變更問題,感興趣的朋友一起看看吧2021-06-06