新聞中心
我通過《回到Future》這個(gè)工作主題開始寫一系列的關(guān)于探討編程語言的Futrure概念的文章。Futrues是非常重要的抽象,甚至隨著異步,事件驅(qū)動,并行和擴(kuò)展系統(tǒng)的發(fā)展顯得更加重要。在第一篇文章中,我們會討論最基本的java.util.concurrent.Future 接口。 接下來我們會跳到其他的框架,庫,甚至是語言。 Future是有限制的,但是有必要去理解future的部分。

成都創(chuàng)新互聯(lián)主要從事網(wǎng)頁設(shè)計(jì)、PC網(wǎng)站建設(shè)(電腦版網(wǎng)站建設(shè))、wap網(wǎng)站建設(shè)(手機(jī)版網(wǎng)站建設(shè))、成都響應(yīng)式網(wǎng)站建設(shè)、程序開發(fā)、網(wǎng)站優(yōu)化、微網(wǎng)站、小程序開發(fā)等,憑借多年來在互聯(lián)網(wǎng)的打拼,我們在互聯(lián)網(wǎng)網(wǎng)站建設(shè)行業(yè)積累了豐富的網(wǎng)站設(shè)計(jì)、做網(wǎng)站、網(wǎng)站設(shè)計(jì)、網(wǎng)絡(luò)營銷經(jīng)驗(yàn),集策劃、開發(fā)、設(shè)計(jì)、營銷、管理等多方位專業(yè)化運(yùn)作于一體。
在一個(gè)單線程應(yīng)用中,當(dāng)你調(diào)用一個(gè)方法只有計(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
contents = downloadContents(new URL("http://www.example.com"));
downloadContents() 看上去是無害的, 但是它需要任意長的時(shí)間來完成。同時(shí),為了減少延遲,在等待結(jié)果的期間,你可能需要同時(shí)獨(dú)立的處理其它的工作。以前你可能會啟動一個(gè)新的線程 或者等待結(jié)果(共享內(nèi)存,鎖,糟糕的 wait()/notify()對).
通過 Future
- public static Future
startDownloading(URL url) { - //...
- }
- final Future
contentsFuture = startDownloading(new URL("http://www.example.com")); - //other computation
- final String contents = contentsFuture.get();
我們馬上會實(shí)現(xiàn) startDownloading(), startDownloading()不會被阻塞,而是等待外部的站點(diǎn)回應(yīng),你理解這一原則是很重要的。 相反,如果它快速返回了,返回一個(gè)輕量級的Future
Future.get()是最重要的方法。它阻塞和等待直到承諾的結(jié)果是可用狀態(tài), 因此如果我們確實(shí)需要這個(gè)字符串,就調(diào)用get() 方法然后等待。 還有一個(gè)接受超時(shí)參數(shù)的重載版本,如果哪里出現(xiàn)問題你就不用一直等待下去,超過設(shè)定時(shí)間就會拋出 TimeoutException。
在某些情況下,你可能想不停地偷偷看看Future是否可用了。這可以通過isDone()來完成。想象一個(gè)情景,你的用戶等待某些異步的計(jì)算,你想讓他知道這種情況, 同時(shí)去做一些其它的計(jì)算:
- final Future
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。如果你遵循這個(gè)模式,就不會忙于每秒百萬次的交替等待和調(diào)用isDone()。
取消futrues是最后一個(gè)我們還沒有覆蓋到的。想象你啟動了異步的工作并且你只能等待一些時(shí)間, 如果2秒鐘后,我們放棄,或者把錯(cuò)誤傳遞出去,或者采用臨時(shí)方案解決它。然而,你是一個(gè)好市民,你應(yīng)該告訴這個(gè)future對象:我不需要你了,你別管了。 那么你可以通過停止過時(shí)的任務(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這個(gè)聲名狼藉的異常的方法,如Thread.sleep(), Object.wait(),Condition.await(),等,甚至包括Future.get(). 如果你被阻塞在這種方法并且有人決定取消你的調(diào)用,他們會毫無疑問的拋出InterruptionException,并發(fā)出有人要打斷當(dāng)前運(yùn)行的任務(wù)。
因此我們現(xiàn)在明白了Future是什么--- 一個(gè)占位符,你可以在未來得到目標(biāo)對象。就像對于一輛車,還沒有制造出來的鑰匙。但是你怎樣才能在應(yīng)用程序中獲得Future的實(shí)例? 兩種最普通的資源是線程池和異步方法(線程池支持)。因此, startDownloading()方法可以被重寫為:
- private final ExecutorService pool = Executors.newFixedThreadPool(10);
- public Future
startDownloading(final URL url) throws IOException { - return pool.submit(new Callable
() { - @Override
- public String call() throws Exception {
- try (InputStream input = url.openStream()) {
- return IOUtils.toString(input, StandardCharsets.UTF_8);
- }
- }
- });
- }
雖然有大量的繁瑣的語法問題,但是基本思想是簡單的: 把需要長時(shí)間運(yùn)行的計(jì)算包裝到可調(diào)用的
你還可以在Spring 和 EJB 碰上Future。比如Spring框架的中你可以為方法加入@Async的注解:
- @Async
- public Future
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,但是這個(gè)方法本身不會與線程池交互或者異步處理。稍后 Spring會代理所有的調(diào)用來startDownloading()并在線程池中執(zhí)行。 在EJB中,相同的特性通過加@Asynchronousannotation 來完成。
我們學(xué)到了許多java.util.concurrent.Future的知識。 現(xiàn)在我們不得不承認(rèn),接口非常有限,特別是在和其它語言作對比的時(shí)候。稍后介紹更多。
你是否不熟悉java 7 中的 try-with-resources Future 模式?那現(xiàn)在最好是遷移到j(luò)ava7上。java 6 在未來2周后將不再維護(hù)更新。
原文鏈接:http://www.oschina.net/translate/java-util-concurrent-future-basics
分享名稱:java.util.concurrent.Future類基礎(chǔ)
網(wǎng)頁網(wǎng)址:http://www.fisionsoft.com.cn/article/djohopc.html


咨詢
建站咨詢
