這篇文章主要講解了“Java并發(fā)框架ExecutorAP類(lèi)型有哪些”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Java并發(fā)框架ExecutorAP類(lèi)型有哪些”吧!

創(chuàng)新互聯(lián)主要從事網(wǎng)頁(yè)設(shè)計(jì)、PC網(wǎng)站建設(shè)(電腦版網(wǎng)站建設(shè))、wap網(wǎng)站建設(shè)(手機(jī)版網(wǎng)站建設(shè))、響應(yīng)式網(wǎng)站建設(shè)、程序開(kāi)發(fā)、網(wǎng)站優(yōu)化、微網(wǎng)站、微信小程序定制開(kāi)發(fā)等,憑借多年來(lái)在互聯(lián)網(wǎng)的打拼,我們?cè)诨ヂ?lián)網(wǎng)網(wǎng)站建設(shè)行業(yè)積累了豐富的網(wǎng)站建設(shè)、成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)、網(wǎng)絡(luò)營(yíng)銷(xiāo)經(jīng)驗(yàn),集策劃、開(kāi)發(fā)、設(shè)計(jì)、營(yíng)銷(xiāo)、管理等多方位專(zhuān)業(yè)化運(yùn)作于一體。
1. Executor 框架是什么?
Executor 框架包含一組用于有效管理工作線(xiàn)程的組件。Executor API 通過(guò) Executors 將任務(wù)的執(zhí)行與要執(zhí)行的實(shí)際任務(wù)解耦。 這是 生產(chǎn)者-消費(fèi)者 模式的一種實(shí)現(xiàn)。
java.util.concurrent.Executors 提供了用于創(chuàng)建工作線(xiàn)程的線(xiàn)程池的工廠(chǎng)方法。
為了使用 Executor 框架,我們需要?jiǎng)?chuàng)建一個(gè)線(xiàn)程池并提交任務(wù)給它以供執(zhí)行。Executor 框架的工作是調(diào)度和執(zhí)行已提交的任務(wù)并從線(xiàn)程池中拿到返回的結(jié)果。
浮現(xiàn)于腦海中的一個(gè)基本的問(wèn)題是,當(dāng)我們創(chuàng)建 java.lang.Thread 的對(duì)象或調(diào)用實(shí)現(xiàn)了 Runnable/Callable 接口來(lái)達(dá)到的程序的并行性時(shí),為什么需要線(xiàn)程池?
答案來(lái)源于兩個(gè)基本面:
為新任務(wù)創(chuàng)建新的線(xiàn)程會(huì)存在額外的線(xiàn)程創(chuàng)建以及銷(xiāo)毀的開(kāi)銷(xiāo)。管理這些線(xiàn)程的生命周期會(huì)明顯增加 CPU 的執(zhí)行時(shí)間。 不進(jìn)行任何限制地為每個(gè)進(jìn)程創(chuàng)建線(xiàn)程會(huì)導(dǎo)致創(chuàng)建大量線(xiàn)程。這些線(xiàn)程會(huì)占用大量?jī)?nèi)存并引起資源的浪費(fèi)。當(dāng)一個(gè)線(xiàn)程利用完 CPU 的時(shí)間片后另一個(gè)線(xiàn)程即將利用CPU的時(shí)間片時(shí),CPU 會(huì)花費(fèi)大量的時(shí)間來(lái)切換線(xiàn)程的上下文。
所有的這些因素都會(huì)導(dǎo)致系統(tǒng)的吞吐量下降。線(xiàn)程池通過(guò)保持線(xiàn)程一直存活并重用這些線(xiàn)程來(lái)克服這個(gè)問(wèn)題。當(dāng)提交到線(xiàn)程池中的任務(wù)多于正在執(zhí)行的線(xiàn)程時(shí),那些多余的任務(wù)將被放到隊(duì)列中。 一旦執(zhí)行任務(wù)的線(xiàn)程有空閑的了,它們會(huì)從隊(duì)列中取下一個(gè)任務(wù)來(lái)執(zhí)行。對(duì)于 JDK 提供的現(xiàn)成的 executors 此任務(wù)隊(duì)列基本是無(wú)界的。
2. Executors 的類(lèi)型
現(xiàn)在我們已經(jīng)了解了 executors 是什么, 讓我們來(lái)看看不同類(lèi)型的 executors。
2.1 SingleThreadExecutor
此線(xiàn)程池 executor 只有一個(gè)線(xiàn)程。它用于以順序方式的形式執(zhí)行任務(wù)。如果此線(xiàn)程在執(zhí)行任務(wù)時(shí)因異常而掛掉,則會(huì)創(chuàng)建一個(gè)新線(xiàn)程來(lái)替換此線(xiàn)程,后續(xù)任務(wù)將在新線(xiàn)程中執(zhí)行。
ExecutorService executorService = Executors.newSingleThreadExecutor()
2.2 FixedThreadPool(n)
顧名思義,它是一個(gè)擁有固定數(shù)量線(xiàn)程的線(xiàn)程池。提交給 executor 的任務(wù)由固定的 n 個(gè)線(xiàn)程執(zhí)行,如果有更多的任務(wù),它們存儲(chǔ)在 LinkedBlockingQueue 里。這個(gè)數(shù)字 n 通常跟底層處理器支持的線(xiàn)程總數(shù)有關(guān)。
ExecutorService executorService = Executors.newFixedThreadPool(4);
2.3 CachedThreadPool
該線(xiàn)程池主要用于執(zhí)行大量短期并行任務(wù)的場(chǎng)景。與固定線(xiàn)程池不同,此線(xiàn)程池的線(xiàn)程數(shù)不受限制。如果所有的線(xiàn)程都在忙于執(zhí)行任務(wù)并且又有新的任務(wù)到來(lái)了,這個(gè)線(xiàn)程池將創(chuàng)建一個(gè)新的線(xiàn)程并將其提交到 executor。只要其中一個(gè)線(xiàn)程變?yōu)榭臻e,它就會(huì)執(zhí)行新的任務(wù)。 如果一個(gè)線(xiàn)程有 60 秒的時(shí)間都是空閑的,它們將被結(jié)束生命周期并從緩存中刪除。
但是,如果管理得不合理,或者任務(wù)不是很短的,則線(xiàn)程池將包含大量的活動(dòng)線(xiàn)程。這可能導(dǎo)致資源紊亂并因此導(dǎo)致性能下降。
ExecutorService executorService = Executors.newCachedThreadPool();
2.4 ScheduledExecutor
當(dāng)我們有一個(gè)需要定期運(yùn)行的任務(wù)或者我們希望延遲某個(gè)任務(wù)時(shí),就會(huì)使用此類(lèi)型的 executor。
ScheduledExecutorService scheduledExecService = Executors.newScheduledThreadPool(1);
可以使用 scheduleAtFixedRate 或 scheduleWithFixedDelay 在 ScheduledExecutor 中定期的執(zhí)行任務(wù)。
scheduledExecService.scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
scheduledExecService.scheduleWithFixedDelay(Runnable command, long initialDelay, long period, TimeUnit unit)
這兩種方法的主要區(qū)別在于它們對(duì)連續(xù)執(zhí)行定期任務(wù)之間的延遲的應(yīng)答。
scheduleAtFixedRate:無(wú)論前一個(gè)任務(wù)何時(shí)結(jié)束,都以固定間隔執(zhí)行任務(wù)。 scheduleWithFixedDelay:只有在當(dāng)前任務(wù)完成后才會(huì)啟動(dòng)延遲倒計(jì)時(shí)。
3. 對(duì)于 Future 對(duì)象的理解
可以使用 executor 返回的 java.util.concurrent.Future 對(duì)象訪(fǎng)問(wèn)提交給 executor 的任務(wù)的結(jié)果。 Future 可以被認(rèn)為是 executor 對(duì)調(diào)用者的響應(yīng)。
Future<String> result = executorService.submit(callableTask);
如上所述,提交給 executor 的任務(wù)是異步的,即程序不會(huì)等待當(dāng)前任務(wù)執(zhí)行完成,而是直接進(jìn)入下一步。相反,每當(dāng)任務(wù)執(zhí)行完成時(shí),executor 在此 Future對(duì)象中設(shè)置它。
調(diào)用者可以繼續(xù)執(zhí)行主程序,當(dāng)需要提交任務(wù)的結(jié)果時(shí),他可以在這個(gè) Future對(duì)象上調(diào)用.get() 方法來(lái)獲取。如果任務(wù)完成,結(jié)果將立即返回給調(diào)用者,否則調(diào)用者將被阻塞,直到 executor 完成此操作的執(zhí)行并計(jì)算出結(jié)果。
如果調(diào)用者不能無(wú)限期地等待任務(wù)執(zhí)行的結(jié)果,那么這個(gè)等待時(shí)間也可以設(shè)置為定時(shí)地。可以通過(guò) Future.get(long timeout,TimeUnit unit) 方法實(shí)現(xiàn),如果在規(guī)定的時(shí)間范圍內(nèi)沒(méi)有返回結(jié)果,則拋出 TimeoutException。調(diào)用者可以處理此異常并繼續(xù)執(zhí)行該程序。
如果在執(zhí)行任務(wù)時(shí)出現(xiàn)異常,則對(duì) get 方法的調(diào)用將拋出一個(gè)ExecutionException。
對(duì)于 Future.get()方法返回的結(jié)果,一個(gè)重要的事情是,只有提交的任務(wù)實(shí)現(xiàn)了java.util.concurrent.Callable接口時(shí)才返回 Future。如果任務(wù)實(shí)現(xiàn)了Runnable接口,那么一旦任務(wù)完成,對(duì) .get() 方法的調(diào)用將返回 null。
另一個(gè)關(guān)注點(diǎn)是 Future.cancel(boolean mayInterruptIfRunning) 方法。此方法用于取消已提交任務(wù)的執(zhí)行。如果任務(wù)已在執(zhí)行,則 executor 將嘗試在mayInterruptIfRunning 標(biāo)志為 true 時(shí)中斷任務(wù)執(zhí)行。
4. Example: 創(chuàng)建和執(zhí)行一個(gè)簡(jiǎn)單的 Executor
我們現(xiàn)在將創(chuàng)建一個(gè)任務(wù)并嘗試在 fixed pool executor 中執(zhí)行它:
public class Task implements Callable<String> { private String message; public Task(String message) { this.message = message; } @Override public String call() throws Exception { return "Hello " + message + "!"; }}
Task 類(lèi)實(shí)現(xiàn) Callable 接口并有一個(gè) String 類(lèi)型作為返回值的方法。 這個(gè)方法也可以?huà)伋?Exception。這種向 executor 拋出異常的能力以及 executor 將此異常返回給調(diào)用者的能力非常重要,因?yàn)樗兄谡{(diào)用者知道任務(wù)執(zhí)行的狀態(tài)。
現(xiàn)在讓我們來(lái)執(zhí)行一下這個(gè)任務(wù):
public class ExecutorExample { public static void main(String[] args) { Task task = new Task("World"); ExecutorService executorService = Executors.newFixedThreadPool(4); Future<String> result = executorService.submit(task); try { System.out.println(result.get()); } catch (InterruptedException | ExecutionException e) { System.out.println("Error occured while executing the submitted task"); e.printStackTrace(); } executorService.shutdown(); }}
我們創(chuàng)建了一個(gè)具有4個(gè)線(xiàn)程數(shù)的 FixedThreadPool executors,因?yàn)檫@個(gè) demo是在四核處理器上開(kāi)發(fā)的。如果正在執(zhí)行的任務(wù)執(zhí)行大量 I/O 操作或花費(fèi)較長(zhǎng)時(shí)間等待外部資源,則線(xiàn)程數(shù)可能超過(guò)處理器的核心數(shù)。
我們實(shí)例化了 Task 類(lèi),并將它提交給 executors 執(zhí)行。 結(jié)果由 Future 對(duì)象返回,然后我們?cè)谄聊簧洗蛴 ?/p>
讓我們運(yùn)行 ExecutorExample 并查看其輸出:
Hello World!
正如所料,任務(wù)追加了問(wèn)候語(yǔ) Hello 并通過(guò) Future object 返回結(jié)果。
最后,我們調(diào)用 executorService 對(duì)象上的 shutdown 來(lái)終止所有線(xiàn)程并將資源返回給 OS。
.shutdown() 方法等待 executor 完成當(dāng)前提交的任務(wù)。 但是,如果要求是立即關(guān)閉 executor 而不等待,那么我們可以使用 .shutdownNow() 方法。
任何待執(zhí)行的任務(wù)都將結(jié)果返回到 java.util.List 對(duì)象中。
我們也可以通過(guò)實(shí)現(xiàn) Runnable 接口來(lái)創(chuàng)建同樣的任務(wù):
public class Task implements Runnable{ private String message; public Task(String message) { this.message = message; } public void run() { System.out.println("Hello " + message + "!"); }}
當(dāng)我們實(shí)現(xiàn) Runnable 時(shí),這里有一些重要的變化。
無(wú)法從 run() 方法得到任務(wù)執(zhí)行的結(jié)果。 因此,我們直接在這里打印。
run() 方法不可拋出任何已受檢的異常。
感謝各位的閱讀,以上就是“Java并發(fā)框架ExecutorAP類(lèi)型有哪些”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Java并發(fā)框架ExecutorAP類(lèi)型有哪些這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
網(wǎng)頁(yè)題目:Java并發(fā)框架ExecutorAP類(lèi)型有哪些
分享鏈接:http://www.chinadenli.net/article48/gidiep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供虛擬主機(jī)、企業(yè)建站、網(wǎng)站建設(shè)、軟件開(kāi)發(fā)、小程序開(kāi)發(fā)、微信小程序
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)