/**
*
*/
package org.googlecode.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.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* 每一个不同的jobkey都会有默认的一套队列机制, 用于较为高效的处理队列中的数据
*
*
*/
public class TaskBufferQueue {
private String taskKey;// 该类任务的主键
private int maximumQueueSize;// 队列最大的长度
private ReentrantLock lock;
private Condition hasResource;// 是否有外部线程可用的信号量
private AtomicInteger counter;// 队列计数器
private QueueChecker checker;// 检查队列的后台线程
private BlockingQueue<Task> jobQueue;// 内部队列
public TaskBufferQueue(String taskKey, int maximumQueueSize,
JobDispatcher jobDispatcher) {
this.taskKey = taskKey;
this.maximumQueueSize = maximumQueueSize;
this.jobDispatcher = jobDispatcher;
this.init();
}
public void init() {
lock = new ReentrantLock();
hasResource = 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(Task t) {
return jobQueue.offer(t);
}
/**
* 通知外部有资源可以执行任务
*/
public void notifyHasResource() {
try {
lock.lock();
hasResource.signalAll();
} 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;
} 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 (job.getTimeOut() > 0) {
if (job.getTimeOut() < System.currentTimeMillis()) {
jobQueue.poll();
counter.decrementAndGet();
continue;
}
}
// 判断是否有资源,并且会先并发减去资源
if (jobDispatcher.checkJobResource(job)) {
// 如果有资源,弹出队列,执行任务,计数器递减
jobQueue.poll();
jobDispatcher.innExecute(job);
counter.decrementAndGet();
} else
blockNoResource(5000);// 如果没有资源就阻塞5秒钟
} else {
blockNoJob(5000);// 如果没有任务就阻塞5秒钟
}
} catch (Exception ex) {
log.error("QueueChecker error!", ex);
}
}
}
public void stopThread() {
try {
isRunning = false;
this.interrupt();
} catch (Exception e) {
// do nothing
}
}
}
}