/** * */ package com.vip.saturn.job.basic; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.jboss.netty.util.internal.ConcurrentHashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.vip.saturn.job.threads.SaturnThreadFactory; /** * @author chembo.huang * */ public class TimeoutSchedulerExecutor { static Logger log = LoggerFactory.getLogger(TimeoutSchedulerExecutor.class); private static ConcurrentHashMap<String, ScheduledThreadPoolExecutor> scheduledThreadPoolExecutorMap = new ConcurrentHashMap<>(); private TimeoutSchedulerExecutor() { } public static synchronized ScheduledThreadPoolExecutor createScheduler(String executorName) { if (!scheduledThreadPoolExecutorMap.containsKey(executorName)) { ScheduledThreadPoolExecutor timeoutExecutor = new ScheduledThreadPoolExecutor( Math.max(2, Runtime.getRuntime().availableProcessors() / 2), new SaturnThreadFactory(executorName + "-timeout-watchdog", false)); timeoutExecutor.setRemoveOnCancelPolicy(true); scheduledThreadPoolExecutorMap.put(executorName, timeoutExecutor); return timeoutExecutor; } return scheduledThreadPoolExecutorMap.get(executorName); } private static ScheduledThreadPoolExecutor getScheduler(String executorName) { return scheduledThreadPoolExecutorMap.get(executorName); } public static final void shutdownScheduler(String executorName) { if (getScheduler(executorName) != null) { getScheduler(executorName).shutdown(); scheduledThreadPoolExecutorMap.remove(executorName); } } // Note that before running this method, method createScheduler() should have been run, so that // getScheduler(executorName) will not be null. public static final void scheduleTimeoutJob(String executorName, int timeoutSeconds, ShardingItemFutureTask shardingItemFutureTask) { ScheduledFuture<?> timeoutFuture = getScheduler(executorName) .schedule(new TimeoutHandleTask(shardingItemFutureTask), timeoutSeconds, TimeUnit.SECONDS); shardingItemFutureTask.setTimeoutFuture(timeoutFuture); } private static class TimeoutHandleTask implements Runnable { private ShardingItemFutureTask shardingItemFutureTask; public TimeoutHandleTask(ShardingItemFutureTask shardingItemFutureTask) { this.shardingItemFutureTask = shardingItemFutureTask; } @Override public void run() { try { if (!shardingItemFutureTask.isDone()) { if (shardingItemFutureTask.getCallable().setTimeout()) { try { shardingItemFutureTask.getCallable().beforeTimeout(); ShardingItemFutureTask.killRunningBusinessThread(shardingItemFutureTask); } catch (Throwable t) {// NOSONAR } } } } catch (Throwable e) { log.error(String.format(SaturnConstant.ERROR_LOG_FORMAT, shardingItemFutureTask.getCallable().getJobName(), e.getMessage()), e); } } } }