package com.vip.saturn.job.basic; import java.lang.Thread.UncaughtExceptionHandler; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.ScheduledFuture; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.vip.saturn.job.SaturnJobReturn; /** * * @author xiaopeng.he * */ public class ShardingItemFutureTask implements Callable<SaturnJobReturn> { private static Logger log = LoggerFactory.getLogger(ShardingItemFutureTask.class); private JavaShardingItemCallable callable; private Callable<?> doneFinallyCallback; private ScheduledFuture<?> timeoutFuture; private Future<?> callFuture; private boolean done = false; //NOSONAR private ExecutorService executorService; public ExecutorService getExecutorService() { return executorService; } public void setExecutorService(ExecutorService executorService) { this.executorService = executorService; } public Future<?> getCallFuture() { return callFuture; } public void setCallFuture(Future<?> callFuture) { this.callFuture = callFuture; } public boolean isDone() { return done; } public void setDone(boolean done) { this.done = done; } public ScheduledFuture<?> getTimeoutFuture() { return timeoutFuture; } public void setTimeoutFuture(ScheduledFuture<?> timeoutFuture) { this.timeoutFuture = timeoutFuture; } public ShardingItemFutureTask(JavaShardingItemCallable callable, Callable<?> doneFinallyCallback) { this.callable = callable; this.doneFinallyCallback = doneFinallyCallback; } public JavaShardingItemCallable getCallable() { return this.callable; } public void reset() { done = false; callable.reset(); } @Override public SaturnJobReturn call() throws Exception { Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler(){ @Override public void uncaughtException(Thread t, Throwable e) { if(e instanceof IllegalMonitorStateException || e instanceof ThreadDeath){ log.error("uncaught:"+e.getMessage()); if(callFuture != null){ callFuture.cancel(false); } if(executorService != null){ executorService.shutdown(); } } } }); try { SaturnJobReturn ret = callable.call(); return ret; } finally { done(); } } private void done() { if (timeoutFuture != null) { timeoutFuture.cancel(true); timeoutFuture = null; } if (done) { return; } done = true; try { try { if (callable.isTimeout()) { callable.onTimeout(); } } catch (Throwable t) { log.error(String.format(SaturnConstant.ERROR_LOG_FORMAT, callable.getJobName(), t.getMessage()), t); } try { if (callable.isForceStop()) { callable.postForceStop(); } } catch (Throwable t) { log.error(String.format(SaturnConstant.ERROR_LOG_FORMAT, callable.getJobName(), t.getMessage()), t); } callable.checkAndSetSaturnJobReturn(); callable.afterExecution(); } finally { try { if (doneFinallyCallback != null) { doneFinallyCallback.call(); } } catch (Exception e) { log.error(String.format(SaturnConstant.ERROR_LOG_FORMAT, callable.getJobName(), e.getMessage()), e); } } } public static void killRunningBusinessThread(ShardingItemFutureTask shardingItemFutureTask) { JavaShardingItemCallable shardingItemCallable = shardingItemFutureTask.getCallable(); Thread businessThread = shardingItemCallable.getCurrentThread(); if (businessThread != null) { try { while (!shardingItemCallable.isBreakForceStop() && !shardingItemFutureTask.isDone()) { businessThread.stop(); if (!shardingItemCallable.isBreakForceStop() && !shardingItemFutureTask.isDone()) { Thread.sleep(50); } else { break; } } } catch (InterruptedException e) {// NOSONAR } } } }