欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時間:2015年07月10日 12:07:56   投稿:goldensun  
這篇文章主要介紹了簡析Java中的util.concurrent.Future接口,作者把future歸結(jié)為在未來得到目標(biāo)對象的占位符,需要的朋友可以參考下

在一個單線程應(yīng)用中,當(dāng)你調(diào)用一個方法只有計(jì)算結(jié)束才會返回結(jié)果( IOUtils.toString()  comes from Apache Commons IO ):
 

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

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

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();

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

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


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

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

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


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

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


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


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

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);
      }
    }
  });
}


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


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

@Async
public Future<String> startDownloading(final URL url) throws IOException {
  try (InputStream input = url.openStream()) {
    return new AsyncResult<>(
        IOUtils.toString(input, StandardCharsets.UTF_8)
    );
  }
}


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

相關(guān)文章

  • 利用javaFX實(shí)現(xiàn)移動一個小球的示例代碼

    利用javaFX實(shí)現(xiàn)移動一個小球的示例代碼

    這篇文章主要介紹了利用javaFX實(shí)現(xiàn)移動一個小球的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Springboot處理異常的常見方式

    Springboot處理異常的常見方式

    SpringBoot框架異常處理有多種處理方式,今天就帶大家了解一下常見的springboot異常處理方式,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • 詳解使用Spring MVC統(tǒng)一異常處理實(shí)戰(zhàn)

    詳解使用Spring MVC統(tǒng)一異常處理實(shí)戰(zhàn)

    本篇文章主要介紹了詳解使用Spring MVC統(tǒng)一異常處理實(shí)戰(zhàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-04-04
  • Java基本數(shù)據(jù)類型(動力節(jié)點(diǎn)java學(xué)院整理)

    Java基本數(shù)據(jù)類型(動力節(jié)點(diǎn)java學(xué)院整理)

    Java數(shù)據(jù)類型(type)可以分為兩大類:基本類型(primitive types)和引用類型(reference types)。下面是動力節(jié)點(diǎn)給大家整理java基本數(shù)據(jù)類型相關(guān)知識,感興趣的朋友一起學(xué)習(xí)吧
    2017-03-03
  • flink?RichFunction之坑及解決

    flink?RichFunction之坑及解決

    這篇文章主要介紹了flink?RichFunction之坑及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Java隨機(jī)生成手機(jī)短信驗(yàn)證碼的方法

    Java隨機(jī)生成手機(jī)短信驗(yàn)證碼的方法

    這篇文章主要介紹了Java隨機(jī)生成手機(jī)短信驗(yàn)證碼的方法,涉及Java數(shù)學(xué)運(yùn)算計(jì)算隨機(jī)數(shù)及字符串操作的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-11-11
  • Spring中獲取Bean方法上的自定義注解問題解析

    Spring中獲取Bean方法上的自定義注解問題解析

    這篇文章主要介紹了Spring中如何獲取Bean方法上的自定義注解,基本的思路就是通過Spring提供的ApplicationContext#getBeansWithAnnotation+反射來實(shí)現(xiàn),需要的朋友可以參考下
    2023-06-06
  • SpringBoot+Jpa項(xiàng)目配置雙數(shù)據(jù)源的實(shí)現(xiàn)

    SpringBoot+Jpa項(xiàng)目配置雙數(shù)據(jù)源的實(shí)現(xiàn)

    本文主要介紹了SpringBoot+Jpa項(xiàng)目配置雙數(shù)據(jù)庫源的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • 短網(wǎng)址的原理與生成方法(Java實(shí)現(xiàn))

    短網(wǎng)址的原理與生成方法(Java實(shí)現(xiàn))

    這篇文章主要給大家介紹了關(guān)于短網(wǎng)址的原理與生成方法,利用的是Java實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • 詳解Spring AOP

    詳解Spring AOP

    本文非常詳細(xì)講解了Spring AOP,本篇文章通過大量的代碼,講解了Spring AOP的使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08

最新評論