java并發(fā)中ExecutorService的具體用法
ExecutorService是java中的一個(gè)異步執(zhí)行的框架,通過使用ExecutorService可以方便的創(chuàng)建多線程執(zhí)行環(huán)境。
本文將會(huì)詳細(xì)的講解ExecutorService的具體使用。
創(chuàng)建ExecutorService
通常來說有兩種方法來創(chuàng)建ExecutorService。
第一種方式是使用Executors中的工廠類方法,例如:
ExecutorService executor = Executors.newFixedThreadPool(10);
除了newFixedThreadPool方法之外,Executors還包含了很多創(chuàng)建ExecutorService的方法。
第二種方法是直接創(chuàng)建一個(gè)ExecutorService, 因?yàn)镋xecutorService是一個(gè)interface,我們需要實(shí)例化ExecutorService的一個(gè)實(shí)現(xiàn)。
這里我們使用ThreadPoolExecutor來舉例:
ExecutorService executorService =
new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
為ExecutorService分配Tasks
ExecutorService可以執(zhí)行Runnable和Callable的task。其中Runnable是沒有返回值的,而Callable是有返回值的。我們分別看一下兩種情況的使用:
Runnable runnableTask = () -> {
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Callable<String> callableTask = () -> {
TimeUnit.MILLISECONDS.sleep(300);
return "Task's execution";
};將task分配給ExecutorService,可以通過調(diào)用xecute(), submit(), invokeAny(), invokeAll()這幾個(gè)方法來實(shí)現(xiàn)。
execute() 返回值是void,他用來提交一個(gè)Runnable task。
executorService.execute(runnableTask);
submit() 返回值是Future,它可以提交Runnable task, 也可以提交Callable task。 提交Runnable的有兩個(gè)方法:
<T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task);
第一個(gè)方法在返回傳入的result。第二個(gè)方法返回null。
再看一下callable的使用:
Future<String> future = executorService.submit(callableTask);
invokeAny() 將一個(gè)task列表傳遞給executorService,并返回其中的一個(gè)成功返回的結(jié)果。
String result = executorService.invokeAny(callableTasks);
invokeAll() 將一個(gè)task列表傳遞給executorService,并返回所有成功執(zhí)行的結(jié)果:
List<Future<String>> futures = executorService.invokeAll(callableTasks);
關(guān)閉ExecutorService
如果ExecutorService中的任務(wù)運(yùn)行完畢之后,ExecutorService不會(huì)自動(dòng)關(guān)閉。它會(huì)等待接收新的任務(wù)。如果需要關(guān)閉ExecutorService, 我們需要調(diào)用shutdown() 或者 shutdownNow() 方法。
shutdown() 會(huì)立即銷毀ExecutorService,它會(huì)讓ExecutorServic停止接收新的任務(wù),并等待現(xiàn)有任務(wù)全部執(zhí)行完畢再銷毀。
executorService.shutdown();
shutdownNow()并不保證所有的任務(wù)都被執(zhí)行完畢,它會(huì)返回一個(gè)未執(zhí)行任務(wù)的列表:
List<Runnable> notExecutedTasks = executorService.shutdownNow();
oracle推薦的最佳關(guān)閉方法是和awaitTermination一起使用:
executorService.shutdown();
try {
if (!executorService.awaitTermination(800, TimeUnit.MILLISECONDS)) {
executorService.shutdownNow();
}
} catch (InterruptedException e) {
executorService.shutdownNow();
}
先停止接收任務(wù),然后再等待一定的時(shí)間讓所有的任務(wù)都執(zhí)行完畢,如果超過了給定的時(shí)間,則立刻結(jié)束任務(wù)。
Future
submit() 和 invokeAll() 都會(huì)返回Future對(duì)象。之前的文章我們已經(jīng)詳細(xì)講過了Future。 這里就只列舉一下怎么使用:
Future<String> future = executorService.submit(callableTask);
String result = null;
try {
result = future.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
ScheduledExecutorService
ScheduledExecutorService為我們提供了定時(shí)執(zhí)行任務(wù)的機(jī)制。
我們這樣創(chuàng)建ScheduledExecutorService:
ScheduledExecutorService executorService
= Executors.newSingleThreadScheduledExecutor();
executorService的schedule方法,可以傳入Runnable也可以傳入Callable:
Future<String> future = executorService.schedule(() -> {
// ...
return "Hello world";
}, 1, TimeUnit.SECONDS);
ScheduledFuture<?> scheduledFuture = executorService.schedule(() -> {
// ...
}, 1, TimeUnit.SECONDS);還有兩個(gè)比較相近的方法:
scheduleAtFixedRate( Runnable command, long initialDelay, long period, TimeUnit unit ) scheduleWithFixedDelay( Runnable command, long initialDelay, long delay, TimeUnit unit )
兩者的區(qū)別是前者的period是以任務(wù)開始時(shí)間來計(jì)算的,后者是以任務(wù)結(jié)束時(shí)間來計(jì)算。
ExecutorService和 Fork/Join
java 7 引入了Fork/Join框架。 那么兩者的區(qū)別是什么呢?
ExecutorService可以由用戶來自己控制生成的線程,提供了對(duì)線程更加細(xì)粒度的控制。而Fork/Join則是為了讓任務(wù)更加快速的執(zhí)行完畢。
本文的代碼請(qǐng)參考https://github.com/ddean2009/learn-java-concurrency/tree/master/ExecutorService
到此這篇關(guān)于java并發(fā)中ExecutorService的具體用法的文章就介紹到這了,更多相關(guān)java ExecutorService使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring框架原理之實(shí)例化bean和@Autowired實(shí)現(xiàn)原理方式
這篇文章主要介紹了Spring框架原理之實(shí)例化bean和@Autowired實(shí)現(xiàn)原理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-05-05
java中ThreadPoolExecutor常識(shí)匯總
這篇文章主要介紹了java中ThreadPoolExecutor常識(shí)匯總,線程池技術(shù)在并發(fā)時(shí)經(jīng)常會(huì)使用到,java中的線程池的使用是通過調(diào)用ThreadPoolExecutor來實(shí)現(xiàn)的,需要的朋友可以參考下2019-06-06
Java+Selenium調(diào)用JavaScript的方法詳解
這篇文章主要為大家講解了java在利用Selenium操作瀏覽器網(wǎng)站時(shí)候,有時(shí)會(huì)需要用的JavaScript的地方,代碼該如何實(shí)現(xiàn)呢?快跟隨小編一起學(xué)習(xí)一下吧2023-01-01
SpringBoot靜態(tài)資源與首頁配置實(shí)現(xiàn)原理深入分析
最近在做SpringBoot項(xiàng)目的時(shí)候遇到了“白頁”問題,通過查資料對(duì)SpringBoot訪問靜態(tài)資源做了總結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-10-10
Apache?SkyWalking?監(jiān)控?MySQL?Server?實(shí)戰(zhàn)解析
這篇文章主要介紹了Apache?SkyWalking?監(jiān)控?MySQL?Server?實(shí)戰(zhàn)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09

