Reprinted -ThreadPoolExecutor inside four kinds of denial strategy (detailed)

1  / * 
2  * asynchronous tasks defined in the thread pool
 . 3   * / 
. 4  @Configuration
 . 5  public  class TaskPoolConfig {
 . 6      @Bean ( ", taskExecutor" )
 . 7      public the Executor, taskExecutor () {
 . 8          the ThreadPoolTaskExecutor is Executor = new new the ThreadPoolTaskExecutor is ();
 . 9          // the core threads 10: the number of threads in the thread pool created when initializing 
10          executor.setCorePoolSize (10 );
 11          // 20 maximum number of threads: the maximum number of threads in the thread pool, only after the buffer queue is full will apply more than the core number of threads the thread 
12 is          executor.setMaxPoolSize (15 );
 13 is          //Buffer queue 200: perform the task queue for the buffer 
14          executor.setQueueCapacity (200 );
 15          // Allow 60 seconds idle thread: when the addition exceeds the number of core threads of the thread reaches the idle time will be destroyed 
16          Executor .setKeepAliveSeconds (60 );
 17          // prefix name of the thread pool: after setting up the thread pool can easily locate where the processing tasks 
18          executor.setThreadNamePrefix ( "taskExecutor-" );
 19          / * 
20          thread pool of rejected tasks strategy: this strategy uses CallerRunsPolicy,
 21          when the thread pool is not dealing with the ability of the strategy runs the rejected task directly in the calling thread of the execute method;
 22          if the executor has been shut down, the task is discarded
 23           * / 
24-          executor.setRejectedExecutionHandler ( new newThreadPoolExecutor.CallerRunsPolicy ());
 25          // 'set to close when the thread pool to wait for all tasks are completed before continuing destruction of other Bean 
26          executor.setWaitForTasksToCompleteOnShutdown ( to true );
 27          // ' task thread pool set waiting time, if over this time we have not destroyed the compulsory destruction, in order to ensure that the application can finally be closed, instead of blocking live. 
28          executor.setAwaitTerminationSeconds (600 );
 29          return Executor;
 30      }
 31 is }

Rejected by the asynchronous strategy due to ponder

 

ExecutorService ThreadPoolExecutor class implements the interface and the Executor interface, you can set the thread pool corePoolSize, maximum thread pool size, AliveTime, refused strategies. Common constructor:

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,

long keepAliveTime, TimeUnit unit,

BlockingQueue<Runnable> workQueue,

RejectedExecutionHandler handler)

 

corePoolSize: thread pool to maintain the minimum number of threads

maximumPoolSize: thread pool to maintain the maximum number of threads

keepAliveTime: thread pool maintenance thread idle time allowed

unit: the thread pool thread maintenance units allowed the idle time

workQueue: buffer queue thread pool used

handler: thread pool strategy rejected tasks

 

When a task (Runnable) method to be added to the thread pool by execute:

 

l If at this time the number of threads in the pool is less than corePoolSize, even if the threads in the pool are idle, but also create a new thread to handle the tasks are added.

2 If at this time is equal to the number of threads in the pool corePoolSize, but workQueue buffer queue is not full, the task is placed in the buffer queue.

3 if this time is greater than the number of threads in the pool corePoolSize, workQueue buffer queue is full, and the number is smaller than the thread pool maximumPoolSize, build a new thread to process the task is added.

4 If this time is greater than the number of threads in the pool corePoolSize, workQueue buffer queue is full, and the number of threads in the pool is equal maximumPoolSize, then processed by the task handler specified policy. That is: the priority processing tasks are: core thread corePoolSize, task queue workQueue, maximum thread maximumPoolSize, if all three are full, use handler processing task rejected.  

When the number of threads in the pool is greater than corePoolSize, if the idle time exceeds a thread keepAliveTime, the thread is terminated. In this way, the thread pool can dynamically adjust the number of threads in the pool.

handler has four options:

 

ThreadPoolExecutor.AbortPolicy()

Java.util.concurrent.RejectedExecutionException throws an exception, for example:

private static class Worker implements Runnable {

public void run() {

System.out.println(Thread.currentThread().getName() + " is running");

}

}

public static void main(String[] args) {

int corePoolSize = 5;

int maxPoolSize = 10;

long keepAliveTime = 5;

BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(10);

 // refused Strategy 1: throws RejectedExecutionException.

RejectedExecutionHandler handler = 

                             new ThreadPoolExecutor.AbortPolicy();

 

ThreadPoolExecutor executor = new ThreadPoolExecutor

(corePoolSize, maxPoolSize, 

keepAliveTime, TimeUnit.SECONDS, 

queue, handler);

for(int i=0; i<100; i++) {

executor.execute(new Worker());

}

executor.shutdown();

}

Results are as follows:

pool-1-thread-2 is running

pool-1-thread-3 is running

Exception in thread "main" java.util.concurrent.RejectedExecutionException

pool-1-thread-1 is running

pool-1-thread-7 is running

pool-1-thread-6 is running

pool-1-thread-4 is running

pool-1-thread-9 is running

pool-1-thread-8 is running

pool-1-thread-5 is running

at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1760)

at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:767)

at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:658)

at concurrent.ThreadPoolDemo.main(ThreadPoolDemo.java:33)

pool-1-thread-10 is running

处理源码如下:

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

            throw new RejectedExecutionException();

        }

策略2:ThreadPoolExecutor.CallerRunsPolicy
用于被拒绝任务的处理程序,它直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务。如下:

RejectedExecutionHandler handler = 

new ThreadPoolExecutor.CallerRunsPolicy();

 

运行如下:

pool-1-thread-7 is running

pool-1-thread-7 is running

pool-1-thread-7 is running

pool-1-thread-7 is running

pool-1-thread-7 is running

pool-1-thread-7 is running

pool-1-thread-2 is running

pool-1-thread-3 is running

pool-1-thread-1 is running

pool-1-thread-8 is running

main is running

main is running

main is running

pool-1-thread-4 is running

pool-1-thread-7 is running

pool-1-thread-7 is running

pool-1-thread-7 is running

处理源码如下:

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

            if (!e.isShutdown()) {

                r.run();

            }

        }

策略3:

RejectedExecutionHandler handler = 

new ThreadPoolExecutor.DiscardOldestPolicy();

这样运行结果就不会有100个线程全部被执行。处理源码如下:

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

            if (!e.isShutdown()) {

                e.getQueue().poll();

                e.execute(r);

            }

        }

 

策略4:ThreadPoolExecutor.DiscardPolicy
用于被拒绝任务的处理程序,默认情况下它将丢弃被拒绝的任务。

运行结果也不会全部执行100个线程。

源码如下,实际就是对线程不执行操作:

    public static class DiscardPolicy implements RejectedExecutionHandler {

        /**

         * Creates a <tt>DiscardPolicy</tt>.

         */

        public DiscardPolicy() { }

 

        /**

         * Does nothing, which has the effect of discarding task r.

         * @param r the runnable task requested to be executed

         * @param e the executor attempting to execute this task

         */

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

        }

    }

 

 

这四种策略是独立无关的,是对任务拒绝处理的四中表现形式。最简单的方式就是直接丢弃任务。但是却有两种方式,到底是该丢弃哪一个任务,比如可以丢弃当前将要加入队列的任务本身(DiscardPolicy)或者丢弃任务队列中最旧任务(DiscardOldestPolicy)。丢弃最旧任务也不是简单的丢弃最旧的任务,而是有一些额外的处理。除了丢弃任务还可以直接抛出一个异常(RejectedExecutionException),这是比较简单的方式。抛出异常的方式(AbortPolicy)尽管实现方式比较简单,但是由于抛出一个RuntimeException,因此会中断调用者的处理过程。除了抛出异常以外还可以不进入线程池执行,在这种方式(CallerRunsPolicy)中任务将有调用者线程去执行。 

 

 

 

用户自定义拒绝策略

实现RejectedExecutionHandler,并自己定义策略模式


再次需要注意的是,ThreadPoolExecutor.submit() 函数,此方法内部调用的execute方法,并把execute执行完后的结果给返回,但如果任务并没有执行的话(被拒绝了),则submit返回的future.get()会一直等到。

 

future 内部其实还是一个runnable,并把command给封装了下,当command执行完后,future会返回一个值。

 

Guess you like

Origin www.cnblogs.com/xiaoshahai/p/11619729.html