java.util.concurrent.RejectedExecutionException


通過對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
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM