Java并發執行器的懶惰開發人員簡介

如果我告訴您util.concurrent API自2004年起提供此類服務,我就會自欺欺人。但是,我想回顧一下一些很酷的功能。 并發專家,現在是時候關閉該窗口了。 所有其他人,請緊緊抓住樂趣。

你不會忘記你的根源

執行程序是具有單個執行方法的根接口。 任何實現Runnable接口的東西都可以作為參數傳遞。 但是,傻傻的執行器不支持Callable。

好消息: ExecutorService接口擴展了Executor,增加了對Callable的支持。 它的實現類是ThreadPoolExecutor。

我要假裝ScheduledExecutorService接口及其實現類ScheduledThreadPoolExecutor不存在,因為它們只是在ExecutorService和ThreadPoolExecutor之上添加了調度功能。 但是,當功能強大但無聊的java.util.Timer不夠用,而功能強大的外部調度程序實在太多了時,請記住此類。

如果您不熟悉并發性,或者忘記了Callable和Runnable之間的區別,則可能需要先閱讀一點,然后再繼續閱讀。 虛擬指南在這里

ExecutorService.submit事實:

這三個提交變量:

將來提交(可調用任務)
將來提交(可運行任務)
將來提交(可運行任務,T結果)

  1. 所述submit的的ExecutorService的方法過載并且可以接受一個CallableRunnable
  2. 由于Runnable的run方法返回void,因此在任務完成時Future.get總是返回null也就Future.get了。
    Future<?>   submit(Runnable task)
  3. 另一個接受Runnable和泛型的重載submit方法將返回您作為第二個參數傳入的結果。
    <T> Future<T>   submit(Runnable task, T result)

事實上,開放代碼( FutureTask ),你會發現, RunnableAdapter頂級嵌套類的Executors只需保存結果,并返回相同的結果run方法完成之后。

static final class RunnableAdapter<T> implements Callable<T> {final Runnable task;final T result;RunnableAdapter(Runnable task, T result) {this.task = task;this.result = result;}public T  [More ...] call() {task.run();return result;}
}

RunnableAdapter源

在這兩種情況下,如果您想要(應該!)終止程序,而不是執行程序線程阻止該程序并進入繁忙循環 ,則應按以下方式調用shutdown方法:

executorService.shutdown()

關閉事實

您可以想象shutdown是購物中心的半關門。 不會有新客戶進入,但現有客戶一旦完成就可以離開購物中心。

重申一下,

  1. shutdown是一種禮貌的方法。 它實際上并不會立即關閉池中的任務。 它只是說不會接受任何新任務。
  2. 除非您使用invokeAll執行任務,否則需要等待所有正在進行的任務完成。 這可以通過調用awaitTermination方法來實現。 (invokeAll并在帖子底部提交示例)
  3. 當前所有任務完成后,執行程序服務將關閉。

如果您需要一種不禮貌的侵入方法,而該方法不關心當前線程是否已完成其任務,那么shutdownNow是您的理想選擇。 但是,不能保證該方法將關閉點上的服務,但這是您必須立即關閉的最接近的方法。

在awaitTermination上,您可以指定超時時間,直到主線程等待池線程完成其任務為止。

ExecutorService executorService=Executors.newFixedThreadPool(10);…future = executorService.submit(getInstanceOfCallable(count,sum));…executorService.shutdown();if (executorService.awaitTermination(10, TimeUnit.SECONDS)){System.out.println('All threads done with their jobs');}

執行者–工廠的家伙

上面的課程都很棒。 但是,例如,您想創建一個單線程執行器,您將編寫類似

new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());

比較一下

Executors.newSingleThreadExecutor()

所以,你去。 Executors是僅具有工廠方法的類,用于使用各種常用默認值創建各種形式的executor服務。 請注意,除了很棒的工廠方法外,它沒有為表帶來任何新功能。

建議您快速查看工廠方法的實現,并檢查它是否適合您的需求。

invokeAll和提交

ExecutorServiceinvokeAll方法的All部分毫不奇怪。 它只是說您需要傳遞Callable的Collection。 再次,正如預期的那樣,該方法直到所有線程完成其任務后才返回。 因此,對于僅在所有工作完成后才對結果感興趣的情況, invokeAll是您的最佳選擇。

另一方面, submit方法在可調用對象被提交給執行者服務之后立即返回。 除非您在Callable call方法中什么都不做,否則理想情況下,當submit方法返回時,工作線程應該正在運行。

以下示例可能對您有用。 這些程序只是嘗試找到所有自然數的和,直到100(當然是蠻力)

package me.rerun.incubator;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;public class ExecutorInvokeAll {public void runApp() throws InterruptedException, ExecutionException{//variable to store the sumAtomicInteger sum=new AtomicInteger();//Use our friendly neighbourhood factory method of the Executors.ExecutorService executorService=Executors.newFixedThreadPool(10);List<Callable<AtomicInteger>> callableList=new ArrayList<Callable<AtomicInteger>>();for (int count = 0; count <= 100;count++) {callableList.add(getInstanceOfCallable(count,sum));}//returns only after all tasks are completeList<Future<AtomicInteger>> resultFuture = executorService.invokeAll(callableList);//Prints 5050 all throughfor (Future<AtomicInteger> future : resultFuture) {//Didn't deliberately put a timeout here for the get method. Remember, the invoke All does not return until the task is done.System.out.println("Status of future : " + future.isDone() +". Result of future : "+future.get().get());}executorService.shutdown();// You might as well call a resultFuture.get(0).get().get() and that would give you the same //result since all your worker threads hold reference to the same atomicinteger sum.System.out.println("Final Sum : "+sum); }//Adds count to the sum and returns the reference of the sum as the resultprivate Callable<AtomicInteger> getInstanceOfCallable(final int count, final AtomicInteger sum) {Callable<AtomicInteger> clientPlanCall=new Callable<AtomicInteger>(){public AtomicInteger call() {sum.addAndGet(count);System.out.println("Intermediate sum :"+sum);return sum;}};return clientPlanCall;}public static void main(String[] args) throws ExecutionException {try {new ExecutorInvokeAll().runApp();} catch (InterruptedException e) {e.printStackTrace();}} }
package me.rerun.incubator;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;public class ExecutorSubmit {public void runApp() throws InterruptedException, ExecutionException{//holder for the total sumAtomicInteger sum=new AtomicInteger();//Use the factory method of ExecutorsExecutorService executorService=Executors.newFixedThreadPool(10);Future<AtomicInteger> future = null;for (int count = 0; count <= 100; count++) {future = executorService.submit(getInstanceOfCallable(count,sum));//prints intermediate sumtry {System.out.println("Status of future : " + future.isDone() +". Result of future : "+future.get(1000, TimeUnit.MILLISECONDS).get());} catch (TimeoutException e) {System.out.println("<IGNORE> Timeout exception for count : "+count);//e.printStackTrace();}//System.out.println("Result of future : "+future.get().get() +".Status of future : " + future.isDone());}executorService.shutdown();if (executorService.awaitTermination(10, TimeUnit.SECONDS)){System.out.println("All threads done with their jobs");}//execSystem.out.println("Final Sum : "+sum);}//Adds count to the sum and returns the reference of the sum as the resultprivate Callable<AtomicInteger> getInstanceOfCallable(final int count, final AtomicInteger sum) {Callable<AtomicInteger> clientPlanCall=new Callable<AtomicInteger>(){public AtomicInteger call() {sum.addAndGet(count);//System.out.println("Intermediate sum :"+sum);return sum;}};return clientPlanCall;}public static void main(String[] args) throws ExecutionException {try {new ExecutorSubmit().runApp();} catch (InterruptedException e) {e.printStackTrace();}} }

進一步閱讀:

亞歷克斯·米勒的驚人博客

亞歷克斯·米勒的并發陷阱

Vogella關于與原始API進行比較的文章

總體上很好地介紹了并發

強烈推薦有關Java并發性的書

祝您編程愉快,別忘了分享!

參考: Rerun.me博客上的JCG合作伙伴 Arun Manivannan的Java并發執行器懶惰開發人員簡介 。


翻譯自: https://www.javacodegeeks.com/2012/10/a-lazy-developers-introduction-to-java.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/371087.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/371087.shtml
英文地址,請注明出處:http://en.pswp.cn/news/371087.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

《我們應該怎樣做需求分析》閱讀筆記

認識&#xff1a;軟件需求分析是貫穿軟件項目從出生到成長或者死亡的&#xff0c;我們必須搞清楚到手的軟件是為了什么要做什么做成什么樣&#xff0c;通過顧客的描述彼此的合作分析需求與業務邏輯&#xff0c;不斷改進從而實現軟件在合理范圍內符合顧客要求。 怎么做&#xff…

Java代碼格式化算法_一個時間格式化的工具類:TimeUtil

源代碼如下&#xff1a;import android.content.Context;import android.text.TextUtils;import android.text.format.DateUtils;import java.text.Format;import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.Date;import java.util.regex.Matcher…

(轉)VS2010/MFC編程入門之前言

雞啄米的C編程入門系列給大家講了C的編程入門知識&#xff0c;大家對C語言在語法和設計思想上應該有了一定的了解了。但是教程中講的例子只是一個個簡單的例程&#xff0c;并沒有可視化窗口。雞啄米在這套VS2010/MFC編程入門教程中將會給大家講解怎樣使用VS2010進行可視化編程&…

JavaOne 2012:JavaFX圖形技巧和竅門

我回到希爾頓&#xff08;皇家宴會廳B&#xff09;看了Richard Bair的&#xff08;Oracle Java客戶架構師&#xff09;的“ JavaFX圖形技巧和竅門”。 Bair與FX Experience相關聯&#xff0c;并且顯然了解JavaFX。 拜爾說&#xff0c;他演講的主題是表演。 他告誡說&#xff0c…

web前端知識點1

1. input屬于窗體元素,層級顯示比flash、其它元素都高。請判斷這句話的正確與否。 錯誤 層級顯示優先級&#xff1a; frameset > 表單元素 > 非表單元素 在html中&#xff0c;幀元素&#xff08;frameset&#xff09;的優先級最高&#xff0c;表單元素比非表單元素的優…

18. 使用模板【從零開始學Spring Boot】

轉&#xff1a;http://blog.csdn.net/linxingliang/article/details/52017098 18.1 使用thymeleaf 整體步驟&#xff1a; &#xff08;1&#xff09; 在pom.xml中引入thymeleaf; &#xff08;2&#xff09; 如何關閉thymeleaf緩存 &#xff08;3&#xff09; …

java單元測試算初級_Java____Eclipse下JUnit單元測試(初級)

給大家分享一個鏈接希望對你們有幫助 http://blog.csdn.net/huangbiao86/article/details/6709742今天看圖片命名唯一的策略時看到有個大大用JUnit測試&#xff0c;神奇的樣子&#xff0c;遂上網搜集來三篇JUnit測試的入門文章&#xff0c;作為參考。原作地址在上面&#xff0c…

Hadoop + Amazon EC2 –更新的教程

在Hadoop的Wiki頁面上放置了一個舊教程&#xff1a; http : //wiki.apache.org/hadoop/AmazonEC2 &#xff0c;但是最近我不得不遵循本教程&#xff0c;并且我注意到它沒有涵蓋某些Amazon新功能。 建議您已經熟悉Hadoop的基礎來遵循本教程&#xff0c;可以在Hadoop的主頁http:…

oracle11g 修改字符集 修改為ZHS16GBK

轉&#xff1a;http://www.cnblogs.com/jay-xu33/p/5210098.html oracle11g 修改字符集 修改為ZHS16GBK1.cmd下,cd到oracle數據庫軟件的服務器端 如&#xff1a;D:\app\Administrator\product\11.2.0\dbhome_1\BIN 2.輸入set ORACLE_SID你想進入的數據庫的那個sid 3.輸入 sqlpl…

瀏覽器內核

瀏覽器的四大內核&#xff1a; Trident&#xff0c;Gecko&#xff0c;Webkit&#xff0c;Blink。 不同的內核對網頁編寫語法的解釋也有不同&#xff0c;進而導致同一個頁面在不同內核的瀏覽器下顯示出來的效果也會有所出入&#xff0c;這也是作為一個前端工程師需要了解不同瀏…

2017.4.14 Java String.split()用法小結

在java.lang包中有String.split()方法,返回是一個數組 我在應用中用到一些,給大家總結一下,僅供大家參考: 1、如果用“.”作為分隔的話,必須是如下寫法,String.split("\\."),這樣才能正確的分隔開,不能用String.split("."); 2、如果用“|”作為分隔的話,必…

java線程統一_Java線程結果不一致

我有一個實現可運行的線程類和一個int計數器作為實例變量。兩種同步方法add和sub。當我以某種方式運行測試類時&#xff0c;它幾次會輸出錯誤的結果。據我了解&#xff0c;當方法同步時&#xff0c;整個對象將被鎖定以供其他線程訪問&#xff0c;這種邏輯每次我們都應該獲得相同…

markdown-Macdown

#標題 [頁面錨點](#name) > <a name"name"></a>文字 **加粗**(Command-B) *斜體*(Command-I) * * * 或者 - -- 無序列表 1. 2. 3. 有序列表 、、、 代碼段 、、、 或者用 ~ 代替 或者 上下空一行每行縮進4個空格 <http://www.baidu.com>鏈…

什么是web標準??

web標準 不是某一個標準&#xff0c;而是一系列標準的集合。網頁主要由三部分組成&#xff1a;結構&#xff08;Structure&#xff09;、表現&#xff08;Presentation&#xff09;和行為&#xff08;Behavior&#xff09;。對應的標準也分三方面&#xff1a;結構化標準語言主…

有沒有更好的Marker方法?

自Java 1.5推出以來&#xff0c;就是否在Java中使用Marker接口進行了廣泛的討論和辯論。 這是因為Java 1.5引入了注釋功能&#xff0c;這些功能幾乎可以解決Marker接口的目的。 本文將涵蓋這場辯論的一個有趣的部分。 定義&#xff1a; Java中的標記接口是一個空接口&#xff…

php jquery ajax登錄,jQuery+Ajax+PHP彈出層異步登錄效果(附源碼下載)

彈出層主要用于展示豐富的頁面信息&#xff0c;還有一個更好的應用是彈出表單層豐富交互應用。常見的應用有彈出登錄表單層&#xff0c;用戶提交登錄信息&#xff0c;后臺驗證登錄成功后&#xff0c;彈出層消失&#xff0c;主頁面局部刷新用戶信息。本文我們將給大家介紹如何使…

【CPU】解決打開360或者Chrome瀏覽器CPU占用過高

cmd 運行&#xff1a; RD /s /q "%USERPROFILE%\AppData\Roaming\Microsoft\Protect"轉載于:https://www.cnblogs.com/zwqh/p/6708398.html

# 20155337 2017-2018-1 《信息安全系統設計基礎》第二周課堂實踐+myod

20155337 2017-2018-1 《信息安全系統設計基礎》第二周課堂實踐myod 因為在課上已經提交了四個實驗&#xff0c;還欠缺最后一個實驗&#xff0c;反省一下自己還是操作不熟練&#xff0c;平時在課下應該多多練習linux的命令訓練。 實踐一 每個* .c一個文件&#xff0c;每個*.h一…

css盒模型中margin很牛逼

css盒子模型&#xff0c;說簡單也簡單&#xff0c;用的時候也有不簡單的。 其中margin的值可以為負值&#xff0c;并且為了實現margin&#xff0c;忽略父級的padding、border、甚至定位。這在布局上很有用&#xff0c;要注意。 ------------ 比如&#xff0c;div1&#xff0…

CometD:Java Web應用程序的Facebook類似聊天

聊天就像吃一塊蛋糕或喝一杯熱咖啡一樣容易。 您是否曾經考慮過自己開發聊天程序&#xff1f; 您知道&#xff0c;聊天不容易。 但是&#xff0c;如果您是開發人員&#xff0c;并且閱讀了本文的結尾&#xff0c;則可以嘗試自己開發一個聊天應用程序&#xff0c;并允許您的用戶通…