在Java5之后,,并發(fā)線程這塊發(fā)生了根本的變化,最重要的莫過于新的啟動(dòng),、調(diào)度,、管理線程的一大堆API了。在Java5以后,,通過Executor來啟動(dòng)線程比用Thread的start()更好,。在新特征中,可以很容易控制線程的啟動(dòng),、執(zhí)行和關(guān)閉過程,,還可以很容易使用線程池的特性。 一,、創(chuàng)建任務(wù) 任務(wù)就是一個(gè)實(shí)現(xiàn)了Runnable接口的類,。 創(chuàng)建的時(shí)候?qū)峳un方法即可。 二,、執(zhí)行任務(wù) 通過java.util.concurrent.ExecutorService接口對(duì)象來執(zhí)行任務(wù),,該接口對(duì)象通過工具類java.util.concurrent.Executors的靜態(tài)方法來創(chuàng)建。 Executors此包中所定義的 Executor,、ExecutorService,、ScheduledExecutorService、ThreadFactory 和 Callable 類的工廠和實(shí)用方法,。 ExecutorService提供了管理終止的方法,,以及可為跟蹤一個(gè)或多個(gè)異步任務(wù)執(zhí)行狀況而生成 Future 的方法。 可以關(guān)閉 ExecutorService,,這將導(dǎo)致其停止接受新任務(wù),。關(guān)閉后,執(zhí)行程序?qū)⒆詈蠼K止,,這時(shí)沒有任務(wù)在執(zhí)行,,也沒有任務(wù)在等待執(zhí)行,并且無法提交新任務(wù),。 executorService.execute(new TestRunnable()),; 1、創(chuàng)建ExecutorService 通過工具類java.util.concurrent.Executors的靜態(tài)方法來創(chuàng)建,。 Executors此包中所定義的 Executor,、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 類的工廠和實(shí)用方法,。 比如,,創(chuàng)建一個(gè)ExecutorService的實(shí)例,ExecutorService實(shí)際上是一個(gè)線程池的管理工具: ExecutorService executorService = Executors.newCachedThreadPool(),; ExecutorService executorService = Executors.newFixedThreadPool(3),; ExecutorService executorService = Executors.newSingleThreadExecutor(); 2,、將任務(wù)添加到線程去執(zhí)行 當(dāng)將一個(gè)任務(wù)添加到線程池中的時(shí)候,,線程池會(huì)為每個(gè)任務(wù)創(chuàng)建一個(gè)線程,,該線程會(huì)在之后的某個(gè)時(shí)刻自動(dòng)執(zhí)行,。 三、關(guān)閉執(zhí)行服務(wù)對(duì)象 executorService.shutdown(),; 四,、綜合實(shí)例 package concurrent; import java.util.concurrent.ExecutorService; /** for (int i = 0; i < 5; i++) { class TestRunnable implements Runnable { 運(yùn)行結(jié)果: ************* a0 *************
五、獲取任務(wù)的執(zhí)行的返回值 在Java5之后,,任務(wù)分兩類:一類是實(shí)現(xiàn)了Runnable接口的類,,一類是實(shí)現(xiàn)了Callable接口的類。兩者都可以被ExecutorService執(zhí)行,,但是Runnable任務(wù)沒有返回值,,而Callable任務(wù)有返回值。并且Callable的call()方法只能通過ExecutorService的submit(Callable<T> task) 方法來執(zhí)行,,并且返回一個(gè) <T> Future<T>,,是表示任務(wù)等待完成的 Future. public interface Callable<V>返回結(jié)果并且可能拋出異常的任務(wù)。實(shí)現(xiàn)者定義了一個(gè)不帶任何參數(shù)的叫做 call 的方法,。 Callable 接口類似于 Runnable,,兩者都是為那些其實(shí)例可能被另一個(gè)線程執(zhí)行的類設(shè)計(jì)的。但是 Runnable 不會(huì)返回結(jié)果,,并且無法拋出經(jīng)過檢查的異常,。 Executors 類包含一些從其他普通形式轉(zhuǎn)換成 Callable 類的實(shí)用方法。 Callable中的call()方法類似Runnable的run()方法,,就是前者有返回值,后者沒有。 當(dāng)將一個(gè)Callable的對(duì)象傳遞給ExecutorService的submit方法,,則該call方法自動(dòng)在一個(gè)線程上執(zhí)行,,并且會(huì)返回執(zhí)行結(jié)果Future對(duì)象。 同樣,,將Runnable的對(duì)象傳遞給ExecutorService的submit方法,,則該run方法自動(dòng)在一個(gè)線程上執(zhí)行,并且會(huì)返回執(zhí)行結(jié)果Future對(duì)象,,但是在該Future對(duì)象上調(diào)用get方法,,將返回null. 遺憾的是,在Java API文檔中,,這塊介紹的很糊涂,,估計(jì)是翻譯人員還沒搞清楚的緣故吧?;蛘哒f是注釋不到位,。下面看個(gè)例子: import java.util.ArrayList; /** //創(chuàng)建10個(gè)任務(wù)并執(zhí)行 //遍歷任務(wù)的結(jié)果
public TaskWithResult(int id) { /** 運(yùn)行結(jié)果: call()方法被自動(dòng)調(diào)用,干活?。,。?nbsp; pool-1-thread-1 Process finished with exit code 0
一個(gè) ExecutorService,,它使用可能的幾個(gè)池線程之一執(zhí)行每個(gè)提交的任務(wù),通常使用 Executors 工廠方法配置,。
線程池可以解決兩個(gè)不同問題:由于減少了每個(gè)任務(wù)調(diào)用的開銷,,它們通??梢栽趫?zhí)行大量異步任務(wù)時(shí)提供增強(qiáng)的性能,并且還可以提供綁定和管理資源(包括執(zhí)行集合任務(wù)時(shí)使用的線程)的方法,。每個(gè) ThreadPoolExecutor 還維護(hù)著一些基本的統(tǒng)計(jì)數(shù)據(jù),,如完成的任務(wù)數(shù)。
為了便于跨大量上下文使用,,此類提供了很多可調(diào)整的參數(shù)和擴(kuò)展掛鉤,。但是,強(qiáng)烈建議程序員使用較為方便的 Executors 工廠方法Executors.newCachedThreadPool()(無界線程池,,可以進(jìn)行自動(dòng)線程回收),、Executors.newFixedThreadPool(int)(固定大小線程池)和Executors.newSingleThreadExecutor()(單個(gè)后臺(tái)線程),它們均為大多數(shù)使用場(chǎng)景預(yù)定義了設(shè)置,。 |
|