package org.googlecode.threadpool;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.googlecode.threadpool.util.NamedThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
/**
* @author zhongfeng
*
*/
public class TimeoutMonitor {
private final static TimeoutMonitor INSTANCE = new TimeoutMonitor();
private final static Logger LOG = LoggerFactory
.getLogger(TimeoutMonitor.class);
private final LoadingCache<String, TimeoutChecker> timeoutCheckerCache = CacheBuilder
.newBuilder().build(new CacheLoader<String, TimeoutChecker>() {
@Override
public TimeoutChecker load(String key) throws Exception {
LOG.debug("Create TimeoutChecker. {} ", key);
TimeoutChecker checker = TimeoutChecker.newInstance(key);
checker.start();
return checker;
}
});;
private TimeoutMonitor() {
}
public FutureTaskDelay addTaskTimeoutMonitor(RunnableTask task) {
TimeoutChecker checker = null;
try {
checker = getTimeoutCheckerCache().get(task.getTaskKey());
} catch (ExecutionException e) {
LOG.error("add task timeout error", e);
}
return checker.addTask(task);
}
public void cancelTaskTimeoutMonitor(RunnableTask task) {
TimeoutChecker checker = null;
try {
checker = getTimeoutCheckerCache().get(task.getTaskKey());
} catch (ExecutionException e) {
LOG.error("cancel task timeout error", e);
}
checker.cancelTask(task);
}
public LoadingCache<String, TimeoutChecker> getTimeoutCheckerCache() {
return timeoutCheckerCache;
}
public static TimeoutMonitor getInstance() {
return INSTANCE;
}
public void shutdown() {
Iterator<Entry<String, TimeoutChecker>> iter = getTimeoutCheckerCache()
.asMap().entrySet().iterator();
while (iter.hasNext()) {
iter.next().getValue().stop();
}
getTimeoutCheckerCache().invalidateAll();
}
public static class TimeoutChecker implements Runnable {
private static final Logger LOG = LoggerFactory
.getLogger(TimeoutChecker.class);
private static final String THREAD_NAME_PREFIX = "TimeoutCheckerThread-";
private String taskKey;
private DelayQueue<FutureTaskDelay> taskDelayQueue;
private ExecutorService exec;
/**
* @param taskKey
*/
private TimeoutChecker(String taskKey) {
this.taskKey = taskKey;
this.taskDelayQueue = new DelayQueue<FutureTaskDelay>();
this.exec = Executors
.newSingleThreadExecutor(new NamedThreadFactory(
THREAD_NAME_PREFIX + taskKey, false));
}
public void start() {
LOG.debug("TimeoutChecker Start.");
exec.execute(this);
}
public void stop() {
taskDelayQueue.clear();
exec.shutdownNow();
}
public FutureTaskDelay addTask(RunnableTask task) {
FutureTaskDelay futureTaskDelay = FutureTaskDelay.newInstance(task);
taskDelayQueue.add(futureTaskDelay);
return futureTaskDelay;
}
public void cancelTask(RunnableTask task) {
taskDelayQueue.remove(FutureTaskDelay.newInstance(task));
}
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
LOG.debug("Timeout,TaskKey: {} ", getTaskKey());
FutureTaskDelay task = taskDelayQueue.take();
task.cancel(true);
} catch (InterruptedException e) {
}
}
}
public DelayQueue<FutureTaskDelay> getTaskDelayQueue() {
return taskDelayQueue;
}
public void setTaskDelayQueue(DelayQueue<FutureTaskDelay> taskDelayQueue) {
this.taskDelayQueue = taskDelayQueue;
}
public String getTaskKey() {
return taskKey;
}
public void setTaskKey(String taskKey) {
this.taskKey = taskKey;
}
public static TimeoutChecker newInstance(String taskKey) {
return new TimeoutChecker(taskKey);
}
@Override
public String toString() {
return "TimeoutChecker [taskDelayQueue=" + taskDelayQueue
+ ", taskKey=" + taskKey + "]";
}
}
}