自定义线程池阻塞式提交任务

public class ContentIndexBuilder {

	/**
	 * 自定义执行器,该执行器具有有界的阻塞式队列,同时具有自定义的阻塞式拒绝执行执行器(也可以使用
	 * {@link ThreadPoolExecutor.CallerRunsPolicy},这种拒绝执行策略在任务队列满后会使任务在调用线程中执行)
	 * 
	 * 这种方式可以避免任务无限制的迅速提交,同时避免任务的放弃
	 */
	private final static int N_THREADS = 5;
	private final static int QUEUE_CAPACITY = 20;
	private final ExecutorService es = new ThreadPoolExecutor(N_THREADS, N_THREADS, 0L, TimeUnit.MILLISECONDS,
			new LinkedBlockingQueue<Runnable>(QUEUE_CAPACITY), new BlockingRejectedExecutionHandler());

	public ContentIndexBuilder() {
		new Thread(new Producer()).start();
	}

	/**
	 * DataBean生产线程
	 * 
	 * @author hasee
	 * 
	 */
	private class Producer implements Runnable {

		@Override
		public void run() {
			while (isWorkingTime()) {
				List<Task> list = getTask();
				for (int i = 0; i < list.size(); i++) {
					Consumer consumer = new Consumer(list.get(i));

					// 通过阻塞式添加的拒绝策略,使得该方法成为阻塞方法
					es.submit(consumer);
				}
			}
		}

		private List<Task> getTask() {
			// TODO Auto-generated method stub
			return null;
		}

		/**
		 * 阻塞式方法,直到返回true
		 * 
		 * 不要递归实现,容易栈溢出
		 * 
		 * @return
		 */
		private boolean isWorkingTime() {
			while (!isTime()) {
				try {
					Thread.sleep(1000 * 60 * 10);
				} catch (InterruptedException e) {
				}
			}
			return true;
		}

		private boolean isTime() {
			// TODO Auto-generated method stub
			return false;
		}
	}

	private class Consumer implements Runnable {
		private final Task task;

		private Consumer(Task task) {
			this.task = task;
		}

		@Override
		public void run() {
			try {
				// TODO deal with task
			} catch (Exception e) {
			}
		}
	}

	/**
	 * 自定义拒绝执行策略:阻塞式地将任务添加至工作队列中
	 * 
	 * @author hasee
	 * 
	 */
	private class BlockingRejectedExecutionHandler implements RejectedExecutionHandler {
		@Override
		public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
			if (!executor.isShutdown()) {
				try {
					// 使用阻塞方法向工作队列中添加任务
					executor.getQueue().put(r);
				} catch (InterruptedException e) {
					executor.execute(r);
				}

			}
		}
	}
}


线程池存储任务的队列一般是有界的,那么当任务队列已满时,新的任务怎么处理呢?

这就要看线程池采用的是那种拒绝策略了。ThreadPoolExecutor中提供了四种拒绝策略,分别是:

CallerRunsPolicy:使用调用线程执行该任务

AbortPolicy:抛出异常并放弃任务

DiscardPolicy:直接放弃任务

DiscardOldestPolicy:放弃旧任务,添加该任务到任务队列

这里我们自定义了一种拒绝策略,即阻塞式添加。当任务队列已满时,调用线程会阻塞,直到任务队列有空位,添加。这种方式不会丢失任务。(其实CallerRunsPolicy也不会丢失任务

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值