/* * <p> * 版权: ©2011 * </p> */ package org.young.isocket.threadpool; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.young.icore.annotation.PropertiesAnnotation; import org.young.icore.util.PropertiesLoaderUtils; /** * <p> * 描述: 每一个不同的jobkey都会有默认的一套队列机制, * 用于较为高效的处理队列中的数据 * </p> * * @see * @author yangjun2 * @email yangjun1120@gmail.com * */ public class JobQueue { private static final Logger logger = LoggerFactory.getLogger(JobQueue.class); /** * 该类任务的主键 */ private String jobKey; /** * 队列最大的长度 */ private int maximumQueueSize; /** * 锁 */ private ReentrantLock lock; /** * 是否有外部线程可用的信号量 */ private Condition hasResource; /** * 当前队列是否有任务的信号量 */ private Condition hasJob; /** * 队列计数器 */ private AtomicInteger counter; /** * 检查队列的后台线程 */ private QueueChecker checker; /** * 内部队列 */ private BlockingQueue<Job> jobQueue; /** * 外部任务调度执行器 */ private JobDispatcher jobDispatcher; /** * 没有任务时sleep时间,单位:微秒 */ @PropertiesAnnotation(name = "nojobsleeptime", resource = "isocket-server.properties") private long noJobSleepTime = 10000; /** * 没有外部线程可用时sleep时间,单位:微秒 */ @PropertiesAnnotation(name = "noresourcesleeptime", resource = "isocket-server.properties") private long noReousrceSleepTime = 2000; public JobQueue(String jobKey, int maximumQueueSize, JobDispatcher jobDispatcher) { this.jobKey = jobKey; this.maximumQueueSize = maximumQueueSize; this.jobDispatcher = jobDispatcher; this.init(); } public void init() { //propery init PropertiesLoaderUtils.setPropertiesFields(this); //other init lock = new ReentrantLock(); hasResource = lock.newCondition(); hasJob = lock.newCondition(); counter = new AtomicInteger(); jobQueue = new LinkedBlockingQueue<Job>(maximumQueueSize); checker = new QueueChecker(); checker.setDaemon(true); checker.start(); } public void clean() { counter.set(0); jobQueue.clear(); checker.stopThread(); checker = null; } public int size() { return counter.get(); } /** * 任务尝试入队列 * @param job * @return */ public boolean offer(Job job) { boolean result = jobQueue.offer(job); if (result) { counter.incrementAndGet(); notifyHasJob(); } return result; } /** * 通知有任务已经入队列 */ public void notifyHasJob() { boolean flag = false; try { flag = lock.tryLock(100, TimeUnit.MILLISECONDS); if (flag) { hasJob.signalAll(); } } catch (InterruptedException ie) { //do nothing; } catch (Exception ex) { logger.error("notifyHasJob error!", ex); } finally { if (flag) { lock.unlock(); } } } /** * 通知外部有资源可以执行任务 */ public void notifyHasResource() { boolean flag = false; try { flag = lock.tryLock(100, TimeUnit.MILLISECONDS); if (flag) hasResource.signalAll(); } catch (InterruptedException ie) { //do nothing; } catch (Exception ex) { logger.error("notifyHasResource error!", ex); } finally { if (flag) lock.unlock(); } } /** * 队列中无任务的阻塞消息 * @param waittime */ public void blockNoJob(long waittime) { boolean flag = lock.tryLock(); if (flag) { try { hasJob.await(waittime, TimeUnit.MILLISECONDS); } catch (InterruptedException ie) { //do nothing; } catch (Exception ex) { logger.error("blockNoJob error!", ex); } finally { lock.unlock(); } } } /** * 外部无可执行资源阻塞消息 * @param waittime */ public void blockNoResource(long waittime) { boolean flag = lock.tryLock(); if (flag) { try { hasResource.await(waittime, TimeUnit.MILLISECONDS); } catch (InterruptedException ie) { //do nothing; } catch (Exception ex) { logger.error("blockNoResource error!", ex); } finally { lock.unlock(); } } } class QueueChecker extends Thread { private boolean isRunning = true; public QueueChecker() { super("queuechecker-" + jobKey); } public void run() { while (isRunning) { try { //尝试获取队列中任务,由于只有一个线程读取,因此可以采用peek + 判断后的poll Job job = jobQueue.peek(); if (job != null) { //判断是否有资源,并且会先并发减去资源 if (jobDispatcher.checkJobResource(job)) { //如果有资源,弹出队列,执行任务,计数器递减 jobQueue.poll(); logger.debug("sumit queue job to threadpool!"); jobDispatcher.getThreadPool().execute(job); counter.decrementAndGet(); ProbeNotifier.notifyTaskDequeued(jobDispatcher, job); } else blockNoResource(noReousrceSleepTime);//如果没有资源就阻塞2秒钟 } else { blockNoJob(noJobSleepTime);//如果没有任务就阻塞10秒钟 } } catch (Exception ex) { logger.error("QueueChecker run error!", ex); } } } public void stopThread() { try { isRunning = false; this.interrupt(); } catch (Exception e) { logger.error("stopThread error!", e); } } } }