ThreadPoolExecutor 四种策略

  1. AbortPolicy: 拒绝策略,不指定为默认值
  2. CallerRunsPolicy: 在任务被拒绝添加后,会调用当前线程池的所在的线程去执行被拒绝的任务
  3. DiscardPolicy: 放弃策略,线程池拒绝的任务直接抛弃,不会抛异常也不会执行
  4. DiscardOldestPolicy: 任务被拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去。

AbortPolicy(拒绝策略)为默认值

源码:可以看到直接抛出运行异常

public static class AbortPolicy implements RejectedExecutionHandler {
        /**
         * Creates an {@code AbortPolicy}.
         */
        public AbortPolicy() { }

        /**
         * Always throws RejectedExecutionException.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         * @throws RejectedExecutionException always
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }

测试代码:

public class Test {

	public static void main(String[] args) {

		ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 2, 0
				,TimeUnit.MICROSECONDS
				,new ArrayBlockingQueue<>(2,true)
				,new ThreadPoolExecutor.AbortPolicy());  // 拒绝策略

		for (int i = 1; i <= 10; i++) {
			System.out.println("添加第"+i+"个线程");
			executor.execute(new MyThread("线程"+i));
			Iterator iterator = executor.getQueue().iterator();
			if (iterator.hasNext()) {
				while (iterator.hasNext()) {
					MyThread thread = (MyThread) iterator.next();
					System.out.println("队列queue中:" + thread.name);
				}
			}else {
				System.out.println("队列中为null");
			}
		}
	}

	// 内部类 主要是为线程起名称方便观察
	static class MyThread implements Runnable {
		String name;
		public MyThread(String name) {
			this.name = name;
		}
		@Override
		public void run() {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("线程:" + Thread.currentThread().getName() + " 执行:" + name + "  run");
		}
	}
}

运行结果乳如下:

添加第1个线程
队列中为null
添加第2个线程
队列queue中:线程2
添加第3个线程
队列queue中:线程2
队列queue中:线程3
添加第4个线程
队列queue中:线程2
队列queue中:线程3
添加第5个线程
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task Test$MyThread@593634ad rejected from java.util.concurrent.ThreadPoolExecutor@20fa23c1[Running, pool size = 2, active threads = 2, queued tasks = 2, completed tasks = 0]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
	at Test.main(Test.java:33)
线程:pool-1-thread-2 执行:线程4  run
线程:pool-1-thread-1 执行:线程1  run
线程:pool-1-thread-1 执行:线程3  run
线程:pool-1-thread-2 执行:线程2  run

分析运行结果:

1.添加第一个任务时,直接执行
  此时队列中:null
2.添加第二个任务时,由于线程核心数为"1"并且核心线程被占用,所以被加入到队列中
  此时队列中:任务二
3.添加第三个任务时同上
  此时队列中:任务二、任务三
4.添加第四个任务时,因为核心任务还在运行,而且任务队列已经满了,所以直接创建新线程执行第四个任务
  此时队列中:任务二、任务三
5.添加第五个任务时,因为 maxPoolSize为2 + 队列BlockingQueue容量为2 = 4 也就是最大承载为4个线程所以执行拒绝策略的rejectedExecution方法,这里就是执行AbortPolicy的rejectedExecution方法直接抛出异常
6.最终,只有四个线程能完成运行。后面的都被拒绝了。

CallerRunsPolicy

源码:当发生拒绝是,调用当前线程池的所在的线程去执行被拒绝的任务

public static class CallerRunsPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code CallerRunsPolicy}.
         */
        public CallerRunsPolicy() { }

        /**
         * Executes task r in the caller's thread, unless the executor
         * has been shut down, in which case the task is discarded.
         *
         * @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) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }

测试代码:其它同上

ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 2, 0
				,TimeUnit.MICROSECONDS
				,new ArrayBlockingQueue<>(2,true)
				,new ThreadPoolExecutor.AbortPolicy());  // 在任务被拒绝添加后,会调用当前线程池的所在的线程去执行被拒绝的任务

运行结果:

添加第1个线程
队列中为null
添加第2个线程
队列queue中:线程2
添加第3个线程
队列queue中:线程2
队列queue中:线程3
添加第4个线程
队列queue中:线程2
队列queue中:线程3
添加第5个线程
线程:main 执行:线程5  run
队列queue中:线程2
队列queue中:线程3
添加第6个线程
线程:pool-1-thread-2 执行:线程4  run
线程:pool-1-thread-1 执行:线程1  run
线程:pool-1-thread-1 执行:线程3  run
线程:main 执行:线程6  run
队列中为null
添加第7个线程
线程:pool-1-thread-2 执行:线程2  run
队列queue中:线程7
添加第8个线程
队列queue中:线程8
添加第9个线程
队列queue中:线程8
队列queue中:线程9
添加第10个线程
队列queue中:线程8
队列queue中:线程9
线程:pool-1-thread-2 执行:线程7  run
线程:pool-1-thread-3 执行:线程10  run
线程:pool-1-thread-2 执行:线程8  run
线程:pool-1-thread-3 执行:线程9  run

分析结果:

添加第五个任务,任务5的时候,同样被线程池拒绝了,因此执行了CallerRunsPolicy的rejectedExecution方法,
这个方法直接执行任务的run方法.因此可以看到任务5是在main线程中执行的
这个策略的缺点就是可能会阻塞主线程。

DiscardPolicy(放弃策略)

源码:被线程池拒绝的任务直接抛弃,不会抛异常也不会执行。

public static class DiscardPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardPolicy}.
         */
        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) {
        }
    }

测试代码:其它同上

ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 2, 0
				,TimeUnit.MICROSECONDS
				,new ArrayBlockingQueue<>(2,true)
				,new ThreadPoolExecutor.DiscardPolicy());
//线程池拒绝的任务直接抛弃,不会抛异常也不会执行。

运行结果:

添加第1个线程
队列中为null
添加第2个线程
队列queue中:线程2
添加第3个线程
队列queue中:线程2
队列queue中:线程3
添加第4个线程
队列queue中:线程2
队列queue中:线程3
添加第5个线程
队列queue中:线程2
队列queue中:线程3
添加第6个线程
队列queue中:线程2
队列queue中:线程3
添加第7个线程
队列queue中:线程2
队列queue中:线程3
添加第8个线程
队列queue中:线程2
队列queue中:线程3
添加第9个线程
队列queue中:线程2
队列queue中:线程3
添加第10个线程
队列queue中:线程2
队列queue中:线程3
线程:pool-1-thread-1 执行:线程1  run
线程:pool-1-thread-2 执行:线程4  run
线程:pool-1-thread-1 执行:线程2  run
线程:pool-1-thread-2 执行:线程3  run

分析结果:

只有四个任务被执行了,其他什么反应都没有,直接丢弃。

DiscardOldestPolicy(放弃最早策略)

源码:在rejectedExecution先从任务队列总弹出最先加入的任务,空出一个位置,然后再次执行execute方法把任务加入队列。

public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardOldestPolicy} for the given executor.
         */
        public DiscardOldestPolicy() { }

        /**
         * Obtains and ignores the next task that the executor
         * would otherwise execute, if one is immediately available,
         * and then retries execution of task r, unless the executor
         * is shut down, in which case task r is instead discarded.
         *
         * @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) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }

测试代码:其它同上

ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 2, 0
				,TimeUnit.MICROSECONDS
				,new ArrayBlockingQueue<>(2,true)
				,new ThreadPoolExecutor.DiscardOldestPolicy());

运行结果:

添加第1个线程
队列中为null
添加第2个线程
队列queue中:线程2
添加第3个线程
队列queue中:线程2
队列queue中:线程3
添加第4个线程
队列queue中:线程2
队列queue中:线程3
添加第5个线程
队列queue中:线程3
队列queue中:线程5
添加第6个线程
队列queue中:线程5
队列queue中:线程6
添加第7个线程
队列queue中:线程6
队列queue中:线程7
添加第8个线程
队列queue中:线程7
队列queue中:线程8
添加第9个线程
队列queue中:线程8
队列queue中:线程9
添加第10个线程
队列queue中:线程9
队列queue中:线程10
线程:pool-1-thread-2 执行:线程4  run
线程:pool-1-thread-1 执行:线程1  run
线程:pool-1-thread-2 执行:线程10  run
线程:pool-1-thread-1 执行:线程9  run

分析结果:

可以看到线程9和线程10顶替了线程2和线程3的位子,其他线程被放弃,既不运行也不抛异常
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值