import com.lancoo.common.utils.Threads;
import com.lancoo.common.utils.spring.SpringUtils;import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;/*** 异步任务管理器* * @author lancoo*/
public class AsyncManager
{/*** 操作延迟10毫秒*/private final int OPERATE_DELAY_TIME = 10;/*** 异步操作任务调度线程池*/private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");/*** 单例模式*/private AsyncManager(){}private static AsyncManager me = new AsyncManager();public static AsyncManager me(){return me;}/*** 执行任务* * @param task 任务*/public void execute(TimerTask task){executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);}/*** 停止任务线程池*/public void shutdown(){Threads.shutdownAndAwaitTermination(executor);}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.util.concurrent.*;/*** 线程相关工具类.* * @author lancoo*/
public class Threads
{private static final Logger logger = LoggerFactory.getLogger(Threads.class);/*** sleep等待,单位为毫秒*/public static void sleep(long milliseconds){try{Thread.sleep(milliseconds);}catch (InterruptedException e){return;}}/*** 停止线程池* 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.* 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.* 如果仍然超時,則強制退出.* 另对在shutdown时线程本身被调用中断做了处理.*/public static void shutdownAndAwaitTermination(ExecutorService pool){if (pool != null && !pool.isShutdown()){pool.shutdown();try{if (!pool.awaitTermination(120, TimeUnit.SECONDS)){pool.shutdownNow();if (!pool.awaitTermination(120, TimeUnit.SECONDS)){logger.info("Pool did not terminate");}}}catch (InterruptedException ie){pool.shutdownNow();Thread.currentThread().interrupt();}}}/*** 打印线程异常信息*/public static void printException(Runnable r, Throwable t){if (t == null && r instanceof Future<?>){try{Future<?> future = (Future<?>) r;if (future.isDone()){future.get();}}catch (CancellationException ce){t = ce;}catch (ExecutionException ee){t = ee.getCause();}catch (InterruptedException ie){Thread.currentThread().interrupt();}}if (t != null){logger.error(t.getMessage(), t);}}
}
import com.lancoo.common.utils.Threads;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;/*** 线程池配置***/
@Configuration
public class ThreadPoolConfig
{// 核心线程池大小private int corePoolSize = 50;// 最大可创建的线程数private int maxPoolSize = 200;// 队列最大长度private int queueCapacity = 1000;// 线程池维护线程所允许的空闲时间private int keepAliveSeconds = 300;@Bean(name = "threadPoolTaskExecutor")public ThreadPoolTaskExecutor threadPoolTaskExecutor(){ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setMaxPoolSize(maxPoolSize);executor.setCorePoolSize(corePoolSize);executor.setQueueCapacity(queueCapacity);executor.setKeepAliveSeconds(keepAliveSeconds);// 线程池对拒绝任务(无线程可用)的处理策略executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());return executor;}/*** 执行周期性或定时任务*/@Bean(name = "scheduledExecutorService")protected ScheduledExecutorService scheduledExecutorService(){return new ScheduledThreadPoolExecutor(corePoolSize,new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),new ThreadPoolExecutor.CallerRunsPolicy()){@Overrideprotected void afterExecute(Runnable r, Throwable t){super.afterExecute(r, t);Threads.printException(r, t);}};}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;import javax.annotation.PreDestroy;/*** 确保应用退出时能关闭后台线程** @author lancoo*/
@Component
public class ShutdownManager
{private static final Logger logger = LoggerFactory.getLogger("sys-user");@PreDestroypublic void destroy(){shutdownAsyncManager();}/*** 停止异步执行任务*/private void shutdownAsyncManager(){try{logger.info("====关闭后台任务任务线程池====");AsyncManager.me().shutdown();}catch (Exception e){logger.error(e.getMessage(), e);}}
}
调用异步时直接使用
或者直接在方法上使用异步注解@Async