一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - 簡析Java中的util.concurrent.Future接口

簡析Java中的util.concurrent.Future接口

2019-12-26 13:15goldensun JAVA教程

這篇文章主要介紹了簡析Java中的util.concurrent.Future接口,作者把future歸結為在未來得到目標對象的占位符,需要的朋友可以參考下

在一個單線程應用中,當你調用一個方法只有計算結束才會返回結果( IOUtils.toString()  comes from Apache Commons IO ):
 

?
1
2
3
4
5
6
7
8
9
public String downloadContents(URL url) throws IOException {
  try(InputStream input = url.openStream()) {
    return IOUtils.toString(input, StandardCharsets.UTF_8);
  }
}
 
//...
 
final Future<String> contents = downloadContents(new URL("http://www.example.com"));

downloadContents() 看上去是無害的, 但是它需要任意長的時間來完成。同時,為了減少延遲,在等待結果的期間,你可能需要同時獨立的處理其它的工作。以前你可能會啟動一個新的線程 或者等待結果(共享內存,鎖,糟糕的 wait()/notify()對).

通過 Future<T> 模式,它會變得明朗:
 

?
1
2
3
4
5
6
7
public static Future<String> startDownloading(URL url) {
  //...
}
 
final Future<String> contentsFuture = startDownloading(new URL("http://www.example.com"));
//other computation
final String contents = contentsFuture.get();

我們馬上會實現 startDownloading(), startDownloading()不會被阻塞,而是等待外部的站點回應,你理解這一原則是很重要的。 相反,如果它快速返回了,返回一個輕量級的Future<String> 對象。 這個對象是一個promise那么將來字符串類型就是可用的,雖然我們不知道什么時候,但是會保留這個引用直到它返有結果返回,你就可以通過Future.get()來獲取它。 換句話說,Future是一個代理或者一個對象的包裝,不是真實的目標對象。一旦異步計算完成,你就可以提取它。 那么Future提供了什么樣的接口呢?

Future.get()是最重要的方法。它阻塞和等待直到承諾的結果是可用狀態, 因此如果我們確實需要這個字符串,就調用get() 方法然后等待。 還有一個接受超時參數的重載版本,如果哪里出現問題你就不用一直等待下去,超過設定時間就會拋出 TimeoutException。


在某些情況下,你可能想不停地偷偷看看Future是否可用了。這可以通過isDone()來完成。想象一個情景,你的用戶等待某些異步的計算,你想讓他知道這種情況, 同時去做一些其它的計算:
 

?
1
2
3
4
5
6
final Future<String> contentsFuture = startDownloading(new URL("http://www.example.com"));
while (!contentsFuture.isDone()) {
  askUserToWait();
  doSomeComputationInTheMeantime();
}
contentsFuture.get();

最后Future.get()調用的內容會保證馬上返回,不會被阻塞,因為Future.isDone() 返回了true。如果你遵循這個模式,就不會忙于每秒百萬次的交替等待和調用isDone()。


取消futrues是最后一個我們還沒有覆蓋到的。想象你啟動了異步的工作并且你只能等待一些時間, 如果2秒鐘后,我們放棄,或者把錯誤傳遞出去,或者采用臨時方案解決它。然而,你是一個好市民,你應該告訴這個future對象:我不需要你了,你別管了。 那么你可以通過停止過時的任務,來節約資源。語法很簡單:
 

?
1
contentsFuture.cancel(true);  //meh...


我們都喜歡隱藏的,布爾類型的參數,對嗎?取消可以通過兩種方式來實現:在任務啟動前通過傳遞false參數來取消,前提是當Future表達的結果計算開始之前。一旦Callable.call()已經運行到一半,那么我們想讓它結束,如果我們傳遞true,那么Future.call()就會具有侵入性,試圖打斷正在運行的工作。你覺得這樣好嗎?現象那些拋出InterruptedException這個聲名狼藉的異常的方法,如Thread.sleep(), Object.wait(),Condition.await(),等,甚至包括Future.get(). 如果你被阻塞在這種方法并且有人決定取消你的調用,他們會毫無疑問的拋出InterruptionException,并發出有人要打斷當前運行的任務。


因此我們現在明白了Future是什么--- 一個占位符,你可以在未來得到目標對象。就像對于一輛車,還沒有制造出來的鑰匙。但是你怎樣才能在應用程序中獲得Future的實例? 兩種最普通的資源是線程池和異步方法(線程池支持)。因此, startDownloading()方法可以被重寫為:
 

?
1
2
3
4
5
6
7
8
9
10
11
12
private final ExecutorService pool = Executors.newFixedThreadPool(10);
 
public Future<String> startDownloading(final URL url) throws IOException {
  return pool.submit(new Callable<String>() {
    @Override
    public String call() throws Exception {
      try (InputStream input = url.openStream()) {
        return IOUtils.toString(input, StandardCharsets.UTF_8);
      }
    }
  });
}


雖然有大量的繁瑣的語法問題,但是基本思想是簡單的: 把需要長時間運行的計算包裝到可調用的<String>,并submit()到線程池,這個線程池包含10個線程。 提交后返回Future<String>的實現,就像以某種方式鏈接到你的任務和線程池。明顯的你的任務不會被立即執行,相反它被放到一個隊列中,稍后會被線程拉出來, 現在需要搞清楚cancel()的兩個特別的意義是什么——你可以取消在隊列中停留的任務,也可以取消早已運行的任務,但這是一件比較復雜的事情。


你還可以在Spring 和 EJB 碰上Future。比如Spring框架的中你可以為方法加入@Async的注解:

?
1
2
3
4
5
6
7
8
@Async
public Future<String> startDownloading(final URL url) throws IOException {
  try (InputStream input = url.openStream()) {
    return new AsyncResult<>(
        IOUtils.toString(input, StandardCharsets.UTF_8)
    );
  }
}


注意,我們簡單地通過包裝結果到AsyncResult來實現Future,但是這個方法本身不會與線程池交互或者異步處理。稍后 Spring會代理所有的調用來startDownloading()并在線程池中執行。 在EJB中,相同的特性通過加@Asynchronousannotation 來完成。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 女暴露狂校园裸露小说 | 日本视频在线免费观看 | 先锋影音 av | 色无月| 天天插综合网 | 久久久影院亚洲精品 | av魔镜收集号 | 四虎影音| 亚洲va久久久噜噜噜久久狠狠 | 日韩日日日 | 99久久精品免费看国产情侣 | 舔比小说 | 大象传媒2021秘密入口 | 91精品国产综合久久福利 | 消息称老熟妇乱视频一区二区 | 大团圆免费阅读全文 | 国产区综合另类亚洲欧美 | 欧美国产在线视频 | 精品国产中文字幕在线视频 | 日本中文字幕一区二区有码在线 | 亚洲图片综合网 | 久久热在线视频精品店 | 亚洲欧美另类在线观看 | 青春草在线观看精品免费视频 | 国产成+人+综合+欧美 亚洲 | 欧洲一级黑寡妇 | 久久国产精品高清一区二区三区 | 女同性互吃奶乳免费视频 | 欧美一二区视频 | 亚洲国产在线综合018 | 青柠影院在线观看免费完整版1 | 国产亚洲精品aaa大片 | 操美女 | 国产区综合另类亚洲欧美 | 波多野结衣中文字幕在线 | 果冻传媒在线播放观看w | 成人免费观看一区二区 | 免费日批视频 | 欧美伦理影院 | 日本人交换乱理伦片 | 亚洲精品成人456在线播放 |