线程池ThreadPoolExecutor与java.util.concurrent.RejectedExecutionException异常

BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(10);//无界队列
	//	queue = new ArrayBlockingQueue<Runnable>(10);	//有界队列
	//	queue = new SynchronousQueue<Runnable>();	//默认
		ThreadPoolExecutor tpe = new ThreadPoolExecutor(5, 20, 1000, TimeUnit.MILLISECONDS, queue);
		for(int i = 0;i<30;i++){	//创建30个线程,并提交任务
			tpe.execute(new Runnable(){
				public void run(){
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(System.currentTimeMillis());
				}
			});
		}
		
		tpe.shutdown();	//关闭线程池

出现RejectedExecutionException异常有两种原因:

1、当你设置的任务缓存队列过小的时候,或者说, 你的线程池里面所有的线程都在干活(线程数== maxPoolSize),并且你的任务缓存队列也已经充满了等待的队列, 这个时候,你再向它提交任务,则会抛出这个异常。

2、执行shutdown后再向线程池中添加任务

               tpe.shutdown();	//关闭线程池
		
		try{
		tpe.execute(new Runnable(){
			public void run(){
				
			}
		});
		}catch(RejectedExecutionException e){
			System.out.println("线程池关闭后不允许向线程池中添加任务");
		}

此时会抛RejectedExecutionException异常。

饱和策略

当队列满时,此时便是饱和策略发挥作用的时候了,JDK中定义了四种饱和策略:

1、AbortPolicy:终止策略是默认的饱和策略,当队列满时,会抛出一个RejectExecutionException异常(第一段代码就是例子),客户可以捕获这个异常,根据需求编写自己的处理代码

2、DiscardPolicy:策略会悄悄抛弃该任务。

3、DiscardOldestPolicy:策略将会抛弃下一个将要执行的任务,如果此策略配合优先队列PriorityBlockingQueue,该策略将会抛弃优先级最高的任务

4、CallerRunsPolicy:调用者运行策略,该策略不会抛出异常,不会抛弃任务,而是将任务回退给调用者线程执行(调用execute方法的线程),由于任务需要执行一段时间,所以在此期间不能提交任务,从而使工作线程有时间执行正在执行的任务。

下面重点演示CallerRunsPolicy策略

@Test
	public void testArrayBlokingQueue(){
		//有界队列
		BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(10);
		//调用者运行策略
		ThreadPoolExecutor tpe = new ThreadPoolExecutor(5, 20, 1000, TimeUnit.MILLISECONDS, queue,new ThreadPoolExecutor.CallerRunsPolicy());
		for(int i = 0;i<100;i++){
			tpe.execute(new Runnable() {
				@Override
				public void run() {
					//目的让更多任务让调用者线程执行
					if(!Thread.currentThread().getName().equals("main")){
						try {
							Thread.sleep(500);
						} catch (InterruptedException e) {
						}
					}
					//会输出很多调用者线程名
					System.out.println(Thread.currentThread().getName());
				}
			});
		}
		tpe.shutdown();
	}



猜你喜欢

转载自blog.csdn.net/nuoWei_SenLin/article/details/78631964