日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Java ThreadPool的使用解析

瀏覽:20日期:2022-08-22 11:56:42

簡介

在java中,除了單個使用Thread之外,我們還會使用到ThreadPool來構建線程池,那么在使用線程池的過程中需要注意哪些事情呢?

一起來看看吧。

java自帶的線程池

java提供了一個非常好用的工具類Executors,通過Executors我們可以非常方便的創建出一系列的線程池:

Executors.newCachedThreadPool,根據需要可以創建新線程的線程池。線程池中曾經創建的線程,在完成某個任務后也許會被用來完成另外一項任務。

Executors.newFixedThreadPool(int nThreads) ,創建一個可重用固定線程數的線程池。這個線程池里最多包含nThread個線程。

Executors.newSingleThreadExecutor() ,創建一個使用單個 worker 線程的 Executor。即使任務再多,也只用1個線程完成任務。

Executors.newSingleThreadScheduledExecutor() ,創建一個單線程執行程序,它可安排在給定延遲后運行命令或者定期執行。

提交給線程池的線程要是可以被中斷的

ExecutorService線程池提供了兩個很方便的停止線程池中線程的方法,他們是shutdown和shutdownNow。

shutdown不會接受新的任務,但是會等待現有任務執行完畢。而shutdownNow會嘗試立馬終止現有運行的線程。

那么它是怎么實現的呢?我們看一個ThreadPoolExecutor中的一個實現:

public List<Runnable> shutdownNow() { List<Runnable> tasks; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); advanceRunState(STOP); interruptWorkers(); tasks = drainQueue(); } finally { mainLock.unlock(); } tryTerminate(); return tasks; }

里面有一個interruptWorkers()方法的調用,實際上就是去中斷當前運行的線程。

所以我們可以得到一個結論,提交到ExecutorService中的任務一定要是可以被中斷的,否則shutdownNow方法將會失效。

先看一個錯誤的使用例子:

public void wrongSubmit(){ Runnable runnable= ()->{ try(SocketChannel sc = SocketChannel.open(new InetSocketAddress('127.0.0.1', 8080))) { ByteBuffer buf = ByteBuffer.allocate(1024); while(true){sc.read(buf); } } catch (IOException e) {e.printStackTrace(); } }; ExecutorService pool = Executors.newFixedThreadPool(10); pool.submit(runnable); pool.shutdownNow(); }

在這個例子中,運行的代碼無法處理中斷,所以將會一直運行。

下面看下正確的寫法:

public void correctSubmit(){ Runnable runnable= ()->{ try(SocketChannel sc = SocketChannel.open(new InetSocketAddress('127.0.0.1', 8080))) {ByteBuffer buf = ByteBuffer.allocate(1024);while(!Thread.interrupted()){ sc.read(buf);} } catch (IOException e) {e.printStackTrace(); } }; ExecutorService pool = Executors.newFixedThreadPool(10); pool.submit(runnable); pool.shutdownNow(); }

我們需要在while循環中加上中斷的判斷,從而控制程序的執行。

正確處理線程池中線程的異常

如果在線程池中的線程發生了異常,比如RuntimeException,我們怎么才能夠捕捉到呢? 如果不能夠對異常進行合理的處理,那么將會產生不可預料的問題。

看下面的例子:

public void wrongSubmit() throws InterruptedException { ExecutorService pool = Executors.newFixedThreadPool(10); Runnable runnable= ()->{ throw new NullPointerException(); }; pool.execute(runnable); Thread.sleep(5000); System.out.println('finished!'); }

上面的例子中,我們submit了一個任務,在任務中會拋出一個NullPointerException,因為是非checked異常,所以不需要顯式捕獲,在任務運行完畢之后,我們基本上是不能夠得知任務是否運行成功了。

那么,怎么才能夠捕獲這樣的線程池異常呢?這里介紹大家幾個方法。

第一種方法就是繼承ThreadPoolExecutor,重寫

protected void afterExecute(Runnable r, Throwable t) { }

protected void terminated() { }

這兩個方法。

其中afterExecute會在任務執行完畢之后被調用,Throwable t中保存的是可能出現的運行時異常和Error。我們可以根據需要進行處理。

而terminated是在線程池中所有的任務都被調用完畢之后才被調用的。我們可以在其中做一些資源的清理工作。

第二種方法就是使用UncaughtExceptionHandler。

Thread類中提供了一個setUncaughtExceptionHandler方法,用來處理捕獲的異常,我們可以在創建Thread的時候,為其添加一個UncaughtExceptionHandler就可以了。

但是ExecutorService執行的是一個個的Runnable,怎么使用ExecutorService來提交Thread呢?

別怕, Executors在構建線程池的時候,還可以讓我們傳入ThreadFactory,從而構建自定義的Thread。

public void useExceptionHandler() throws InterruptedException { ThreadFactory factory =new ExceptionThreadFactory(new MyExceptionHandler()); ExecutorService pool =Executors.newFixedThreadPool(10, factory); Runnable runnable= ()->{ throw new NullPointerException(); }; pool.execute(runnable); Thread.sleep(5000); System.out.println('finished!'); } public static class ExceptionThreadFactory implements ThreadFactory { private static final ThreadFactory defaultFactory =Executors.defaultThreadFactory(); private final Thread.UncaughtExceptionHandler handler; public ExceptionThreadFactory(Thread.UncaughtExceptionHandler handler) { this.handler = handler; } @Override public Thread newThread(Runnable run) { Thread thread = defaultFactory.newThread(run); thread.setUncaughtExceptionHandler(handler); return thread; } } public static class MyExceptionHandler implements Thread.UncaughtExceptionHandler { @Override public void uncaughtException(Thread t, Throwable e) { } }

上面的例子有點復雜了, 有沒有更簡單點的做法呢?

有的。ExecutorService除了execute來提交任務之外,還可以使用submit來提交任務。不同之處是submit會返回一個Future來保存執行的結果。

public void useFuture() throws InterruptedException { ExecutorService pool = Executors.newFixedThreadPool(10); Runnable runnable= ()->{ throw new NullPointerException(); }; Future future = pool.submit(runnable); try { future.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } Thread.sleep(5000); System.out.println('finished!'); }

當我們在調用future.get()來獲取結果的時候,異常也會被封裝到ExecutionException,我們可以直接獲取到。

線程池中使用ThreadLocal一定要注意清理

我們知道ThreadLocal是Thread中的本地變量,如果我們在線程的運行過程中用到了ThreadLocal,那么當線程被回收之后再次執行其他的任務的時候就會讀取到之前被設置的變量,從而產生未知的問題。

正確的使用方法就是在線程每次執行完任務之后,都去調用一下ThreadLocal的remove操作。

或者在自定義ThreadPoolExecutor中,重寫beforeExecute(Thread t, Runnable r)方法,在其中加入ThreadLocal的remove操作。

本文的代碼:

https://github.com/ddean2009/learn-java-base-9-to-20/tree/master/security

以上就是Java ThreadPool的使用解析的詳細內容,更多關于Java ThreadPool的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
免费看精品久久片| 亚洲综合丁香| 日韩天堂av| 亚洲播播91| 91综合视频| 精品亚洲二区| 国产三级精品三级在线观看国产| 玖玖玖国产精品| 亚洲专区一区| 日韩一区中文| 国产福利一区二区三区在线播放| 国产欧美日韩一级| 福利视频一区| 黄色成人精品网站| 国产精品亚洲四区在线观看| 国产激情久久| 三上亚洲一区二区| 中文在线一区| 国产一区2区在线观看| 日韩欧美三区| 不卡专区在线| 丝袜美腿一区| 国产精品激情电影| 欧美专区在线| 日韩精品不卡一区二区| 国产麻豆一区二区三区精品视频| 日本在线高清| 亚洲精品麻豆| 日韩1区2区| 你懂的国产精品| 欧美国产先锋| 国产suv精品一区二区四区视频| 国产一区丝袜| 中文字幕在线免费观看视频| 神马日本精品| 中文无码久久精品| 亚洲综合福利| 国产精品久久久久av蜜臀| 日本一二区不卡| 日韩一区二区免费看| 日韩精品a在线观看91| 亚洲不卡av不卡一区二区| 福利一区二区三区视频在线观看| 91免费精品| 国产精品一区二区三区av| 亚洲香蕉网站| 久久久精品日韩| 在线看片国产福利你懂的| 91九色综合| 国产婷婷精品| 播放一区二区| 国产精品久久久久久久久久10秀| 国产伊人久久| 91精品一区二区三区综合在线爱| 精品视频99| 国产韩日影视精品| 99久久精品国产亚洲精品| 国产成人久久精品麻豆二区| 亚洲精品福利电影| 国产成人精品一区二区三区免费| 欧美a级片一区| 蜜臀av在线播放一区二区三区 | 亚洲第一精品影视| 99热免费精品| 老牛国产精品一区的观看方式| 日韩欧美1区| 黄色网一区二区| 尹人成人综合网| 国产精品嫩模av在线| 91精品国产乱码久久久久久久| 日本在线不卡视频一二三区| 日韩欧美视频专区| 国产欧美日韩视频在线| 在线亚洲观看| 亚洲综合专区| 欧美日韩亚洲一区| 国产专区一区| 日韩国产一区二| 日韩精品一二三区| 婷婷综合一区| 国产精品一区毛片| 欧产日产国产精品视频| 亚洲精品系列| 午夜av成人| 午夜国产精品视频| 国产精品一区二区精品视频观看| 国产福利一区二区精品秒拍| 亚洲欧美日韩国产一区二区| 日本一区二区中文字幕| 久久精品国产亚洲夜色av网站 | 欧美日韩国产一区二区三区不卡 | 久久av日韩| 亚洲性视频在线| 久久一区二区三区喷水| 蜜桃久久久久| 欧美专区一区| 最新国产精品久久久| 欧美精品一二| 日韩精品中文字幕第1页| 国产精品视频一区二区三区综合 | 亚洲黄色影院| 国内精品美女在线观看| 欧美一区网站| 亚洲精品国产精品粉嫩| 在线亚洲欧美| 夜夜嗨一区二区| 欧美成人亚洲| 99久久亚洲精品| 日韩不卡免费高清视频| 欧洲一区二区三区精品| 日本不良网站在线观看| 国产福利片在线观看| 国产激情在线播放| 中文字幕在线官网| 波多视频一区| 亚洲www啪成人一区二区| 精品无人区麻豆乱码久久久| 国产精品久久久一区二区| 欧美一区二区三区久久精品| 69精品国产久热在线观看| 欧美亚洲色图校园春色| 国产欧美一区二区三区米奇 | 亚洲v天堂v手机在线| 日韩在线观看一区二区| 久久xxxx精品视频| 日韩专区在线视频| 亚洲欧洲美洲国产香蕉| 天堂俺去俺来也www久久婷婷| 亚洲日本欧美| 亚洲开心激情| 亚州精品视频| 日韩在线黄色| 欧美在线看片| 精品国产午夜| 91视频一区| 欧美日韩一区二区三区视频播放| 亚洲欧美日韩高清在线| 蜜臀av性久久久久蜜臀aⅴ四虎| 亚洲精品成人一区| 国产精品tv| 国产白浆在线免费观看| 色婷婷精品视频| 国精品一区二区三区| 亚洲欧美日韩国产一区二区| 中文字幕日韩亚洲| 日韩精品视频在线看| 国产精品对白久久久久粗| 精品视频一区二区三区四区五区| 久久久久久久欧美精品| 18国产精品| 国内不卡的一区二区三区中文字幕| 精品视频91| 亚洲精品一级二级| 国产精品视区| 日韩av一区二区三区四区| 国产精品成人国产| 日韩一区二区三区免费播放| 亚洲国产成人精品女人| 亚洲欧美日本国产| 久久久精品国产**网站| 999精品色在线播放| 亚洲69av| 色黄视频在线观看| 夜夜嗨av一区二区三区网站四季av| 亚洲91在线| 久久久久久色 | 日韩精品福利一区二区三区| 精品三级av| 91久久国产| 日韩精品第一| 91tv亚洲精品香蕉国产一区| 国产亚洲精品自拍| 久久av影视| aa国产精品| 美腿丝袜亚洲三区| 亚洲精品网址| 欧美黄页在线免费观看| 自拍日韩欧美| 国产精品久久久网站| 色婷婷狠狠五月综合天色拍| 亚洲啊v在线免费视频| 亚洲成人不卡| 欧美精品中文字幕亚洲专区| 香蕉精品久久| 另类小说一区二区三区| 爽好久久久欧美精品| 国产极品模特精品一二| 国产亚洲午夜| caoporn视频在线| 日本综合视频| 99久久夜色精品国产亚洲1000部| 7777精品| 亚洲中午字幕| 中文字幕高清在线播放| 日韩不卡在线观看日韩不卡视频| 女生影院久久| 久久国产人妖系列| 午夜亚洲精品| 亚洲成av在线| 精品视频在线一区二区在线|