解決java.util.concurrent.RejectedExecutionException
前言
昨晚12:00執行自動化測試指令碼時遇到了java.util.concurrent.RejectedExecutionException這個異常,從異常名稱裡很容易分析出是提交的任務被執行緒池拒絕了。檢視原始碼發現是在Activity裡,AsyncTask是在自定義的執行緒池的執行的,但是onDestory函式裡卻是先顯示呼叫了執行緒池的shutdown方法,然後才是AsyncTask的cancel操作,因此可能導致任務被拒絕。ThreadPoolExecutor
一個ExecutorService,它使用可能的幾個執行緒池之一執行每個提交的任務,通常使用Executors工廠方法配置,但是檢視原始碼,發現工廠方法也是統一呼叫了ThreadPoolExecutor類,以為例,原始碼如下:雖然我一直認同程式設計師應使用較為方便的Executors工廠方法Executors.newCachedThreadPool() (無界執行緒池,可以進行自動執行緒回收)、Executors.newFixedThreadPool(int)(固定大小執行緒池)和Executors.newSingleThreadExecutor()(單個後臺執行緒),但是通過原始碼我們可以發現最後他們均呼叫了ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) 方法,因此我們在分析java.util.concurrent.RejectedExecutionException之前,需要深入學習一下ThreadPoolExecutor的使用。public class Executors { public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory); } }
核心池和最大池的大小
保持活動時間
排隊
所有BlockingQueue都可用於傳輸和保持提交的任務。可以使用此佇列與池大小進行互動:- 如果執行的執行緒少於corePoolSize,則Executor始終首選新增新的執行緒,而不進行排隊。
- 如果執行的執行緒等於或多於corePoolSize,則Executor始終首選將請求加入佇列,而不新增新的執行緒。
- 如果無法將請求加入佇列,則建立新的執行緒,除非建立此執行緒超出maximumPoolSize,在這種情況下,任務將被拒絕(丟擲RejectedExecutionException)。
- 直接提交。工作佇列的預設選項是synchronousQueue,它將任務直接提交給執行緒而不保持它們。在此,如果不存在可用於立即執行任務的執行緒,則試圖把任務加入佇列將失敗,因此會構造一個新的執行緒。此策略可以避免在處理可能具有內部依賴性的請求集時出現鎖。直接提交通常要求無界maximumPoolSizes以避免拒絕新提交的任務。當命令以超過佇列所能處理的平均數連續到達時,此策略允許無界執行緒具有增加的可能性。
- 無界佇列。使用無界佇列(例如,不具有預定義容量的LinkedBlockingQueue)將導致在所有corePoolSize執行緒都忙時新任務在佇列中等待。這樣,建立的執行緒就不會超過corePoolSize(因此,maximumPoolSize的值也就無效了)。
- 有界佇列。當使用有限的maximumPoolSizes時,有界佇列(如ArrayBlockingQueue)有助於防止資源耗盡,但是可能較難調整和控制。佇列大小和最大池大小可能需要相互折衷:使用大型佇列和小型池可以最大限度的降低CPU使用率、作業系統資源和上下文切換開銷,但是可能導致人工降低吞吐量。如果任務頻繁阻塞,則系統可能為超過您許可的更多執行緒安排時間,使用小型佇列通常要求較大的池大小,CPU使用率較高,但是可能遇到不可接受的排程開銷,這樣可會降低吞吐量。
終止
程式不再引用的池沒有剩餘執行緒會自動shutdown。如果希望確保回收取消引用的池(即使使用者忘記呼叫shutdown()),則必須安排未使用的執行緒最終終止。分析
通過對ThreadPoolExecutor類分析,引發java.util.concurrent.RejectedExecutionException主要有兩種原因:1. 執行緒池顯示的呼叫了shutdown()之後,再向執行緒池提交任務的時候,如果你配置的拒絕策略是ThreadPoolExecutor.AbortPolicy的話,這個異常就被會丟擲來。2. 當你的排隊策略為有界佇列,並且配置的拒絕策略是ThreadPoolExecutor.AbortPolicy,當執行緒池的執行緒數量已經達到了maximumPoolSize的時候,你再向它提交任務,就會丟擲ThreadPoolExecutor.AbortPolicy異常。顯示關閉掉執行緒池
這一點很好理解。比如說,你向一個倉庫去存放貨物,一開始,倉庫管理員把門給你打開了,你放了第一件商品到倉庫裡,但是當你放好出去後,有人把倉庫門關了,那你下次再來存放物品時,你就會被拒絕。示例程式碼如下:import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TextExecutor {
public ExecutorService fixedExecutorService = Executors.newFixedThreadPool(5);
public ExecutorService cachedExecutorService = Executors.newCachedThreadPool();
public ExecutorService singleExecutorService = Executors.newSingleThreadExecutor();
public void testExecutorException() {
for (int i = 0; i < 10; i ++) {
fixedExecutorService.execute(new SayHelloRunnable());
fixedExecutorService.shutdown();
}
}
private class SayHelloRunnable implements Runnable {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
System.out.println("hello world!");
}
}
}
public static void main(String[] args) {
TextExecutor testExecutor = new TextExecutor();
testExecutor.testExecutorException();
}
}
解決方案
1. 不要顯示的呼叫shutdown方法,例如Android裡,只有你在Destory方法裡cancel掉AsyncTask,則執行緒池裡沒有活躍執行緒會自己回收自己。2. 呼叫執行緒池時,判斷是否已經shutdown,通過API方法isShutDown方法判斷,示例程式碼:import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TextExecutor {
public ExecutorService fixedExecutorService = Executors.newFixedThreadPool(5);
public ExecutorService cachedExecutorService = Executors.newCachedThreadPool();
public ExecutorService singleExecutorService = Executors.newSingleThreadExecutor();
public void testExecutorException() {
for (int i = 0; i < 10; i ++) {
// 增加isShutdown()判斷
if (!fixedExecutorService.isShutdown()) {
fixedExecutorService.execute(new SayHelloRunnable());
}
fixedExecutorService.shutdown();
}
}
private class SayHelloRunnable implements Runnable {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
System.out.println("hello world!");
}
}
}
public static void main(String[] args) {
TextExecutor testExecutor = new TextExecutor();
testExecutor.testExecutorException();
}
}
執行緒數量超過maximumPoolSize
示例程式碼裡使用了自定義的ExecutorService,可以復現這種問題:import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class TextExecutor {
public ExecutorService fixedExecutorService = Executors.newFixedThreadPool(5);
public ExecutorService cachedExecutorService = Executors.newCachedThreadPool();
public ExecutorService singleExecutorService = Executors.newSingleThreadExecutor();
public ExecutorService customerExecutorService = new ThreadPoolExecutor(3, 5, 0, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>());
public void testExecutorException() {
for (int i = 0; i < 10; i ++) {
// 增加isShutdown()判斷
if (!fixedExecutorService.isShutdown()) {
fixedExecutorService.execute(new SayHelloRunnable());
}
fixedExecutorService.shutdown();
}
}
public void testCustomerExecutorException() {
for (int i = 0; i < 100; i ++) {
customerExecutorService.execute(new SayHelloRunnable());
}
}
private class SayHelloRunnable implements Runnable {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
System.out.println("hello world!");
}
}
}
public static void main(String[] args) {
TextExecutor testExecutor = new TextExecutor();
testExecutor.testCustomerExecutorException();;
}
}
解決方案
1. 儘量調大maximumPoolSize,例如設定為Integer.MAX_VALUE public ExecutorService customerExecutorService = new ThreadPoolExecutor(3, Integer.MAX_VALUE, 0, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>());
2. 使用其他排隊策略,例如LinkedBlockingQueue<span style="white-space:pre"> </span>public ExecutorService customerExecutorService = new ThreadPoolExecutor(3, 5, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
相關推薦
解決java.util.concurrent.RejectedExecutionException
前言昨晚12:00執行自動化測試指令碼時遇到了java.util.concurrent.RejectedExecutionException這個異常,從異常名稱裡很容易分析出是提交的任務被執行緒池拒絕了。檢視原始碼發現是在Activity裡,AsyncTask是在自定義的執行
Android解決Java.util.concurrent.ExecutionException: com.Android.ide.common.process.ProcessException:異常
錯誤: Error:Execution failed for task ':app:mergeDebugResources'. > Error: java.util.concurrent.ExecutionException: com.android.ide.common.process.P
java.util.concurrent.RejectedExecutionException異常發生的時機
概述線上程池的使用過程中,我們有時候會遇到下面的異常那麼什麼時候會發生這個異常呢1.執行緒池關閉以後,再次提交任務2.提交執行緒的數量大於最大執行緒數+任務佇列中排隊的個數接下來我們模擬一下情況一 ExecutorService service = Execut
出現java.util.concurrent.RejectedExecutionException或者Thread pool exhausted怎麼辦?
RejectedExecutionException表示執行緒池已經達到最大值,並且沒有空閒連,拒絕執行了一些任務。 Thread pool exhausted通常是min和max不一樣大時,表示當前已建立的連線用完,進行了一次擴充,建立了新執行緒,但不影響執行。 原因可
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleExcept問題解決方案
log blank article 問題解決 安裝路徑 model row spa exec 在部署Dynamic Web Project時,如果正確配置web.xml或者標註時,仍然出現以上異常的話,可以嘗試以下內容講解的方法: 首先,雙擊eclipse中的serve
Android Studio出現java.util.concurrent.ExecutionException: com.android.ide.common.process.ProcessException的總結和解決方法
logo ide roc for deb execution 所有 不同類 util 1. Error:Execution failed for task ‘mergeDebugAndroidTestResources‘. > Error: java.util.c
java.util.concurrent.ExecutionException 錯誤解決。
錯誤: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].
spring cloud java.util.concurrent.TimeoutException的三種解決方式
spring cloud java.util.concurrent.TimeoutException解決方式 設定熔斷器檢測時間(預設1秒) hystrix.command.default.exec
解決錯誤: java.util.concurrent.ExecutionException: java.lang.UnsupportedOperationException
錯誤:Error:Execution failed for task ':app:transformClassesWithDexForReDebug'.>com.android.build.api.transform.TransformException:com.and
分享以下編譯錯誤:java.util.concurrent.ExecutionException: java.lang.UnsupportedOperationException的一種解決方法
最近一個專案從eclipse轉為了AS專案,修改依賴後第一次執行時碰到如下錯誤: Error:Execution failed for task ':videoPlayer:transformClassesWithDexForDebug'. > com.android
簡述synchronized和java.util.concurrent.locks.Lock異同
pda 阻塞 例如 好的 nbsp 釋放 非阻塞 ant 方法 主要相同點:Lock能完成synchronized所實現的所有功能。主要不同點:Lock有比synchronized更精確的線程語義和更好的性能。syncronized會自動釋放鎖,而Lock一定要程序員手動釋
聊聊高並發(二十四)解析java.util.concurrent各個組件(六) 深入理解AQS(四)
sar 成功 通知 ati help write ng- ads 同步 近期總體過了下AQS的結構。也在網上看了一些講AQS的文章,大部分的文章都是泛泛而談。又一次看了下AQS的代碼,把一些新的要點拿出來說一說。 AQS是一個管程。提供了一個主要的同步器的
本地啟動tomcat的時候報java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: PermGen space
分析 man collect blog app 實例 heap bat linux系統 1、問題:我在tomcat中放入了大量的war包,啟動的時候報:java.util.concurrent.ExecutionException: java.lang.OutOfMemor
java.util.concurrent CyclicBarrier類
實現 .cn tint style pub interrupt com err rup CyclicBarrier類: 原文:一個同步輔助類,它允許一組線程互相等待,直到到達某個公共屏障點 (common barrier point)。在涉及一組固定大小的線程的程序中,
本地啟動tomcat的時候報內存溢出錯誤:java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: PermGen space
技術分享 exce info compile 界面 current msi lang ech 問題分析: PermGen space的全稱是Permanent Generation space,是指內存的永久保存區域,這塊內存主要是被JVM存放Class和Meta信息的
Java學習筆記—多線程(java.util.concurrent並發包概括,轉載)
java學習 read 可見性 locks body bsp wait lock ble 一、描述線程的類:Runable和Thread都屬於java.lang包 二、內置鎖synchronized屬於jvm關鍵字,內置條件隊列操作接口Object.wait()/notif
Java學習筆記—多線程(java.util.concurrent.locks包,轉載)
www 直接 一定的 比較 得到 非公平鎖 關於 無法 returns 一.synchronized的缺陷 synchronized是java中的一個關鍵字,也就是說是Java語言內置的特性。那麽為什麽會出現Lock呢? 如果一個代碼塊被synchronized修飾
Java學習筆記—多線程(原子類,java.util.concurrent.atomic包,轉載)
支持 位置 dset 賦值 嵌入 imp ans 匯編指令 sta 原子類 Java從JDK 1.5開始提供了java.util.concurrent.atomic包(以下簡稱Atomic包),這個包中 的原子操作類提供了一種用法簡單、性能高效、線程安全地更新一個變量的方
Java學習筆記—多線程(並發工具類,java.util.concurrent.atomic包)
配對 初始 訪問 接收 iter nco .get 執行 string 在JDK的並發包裏提供了幾個非常有用的並發工具類。CountDownLatch、CyclicBarrier和Semaphore工具類提供了一種並發流程控制的手段,Exchanger工具類則提供了在線程間
Java基礎知識-java.util.concurrent包下常見類的使用
finall iss con value 通信 out 否則 app ted 一,Condition 一個場景,兩個線程數數,同時啟動兩個線程,線程A數1、2、3,然後線程B數4、5、6,最後線程A數7、8、9,程序結束,這涉及到線程之間的通信。 public class