异步工具
异步工具类,方便记录日志
线程类
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.*; /** * 线程相关工具类 * * @Author szw * @Date 2020/2/13 18:06 * @Version 1.0 **/ 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.jarvis.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; /** * 线程池配置 * * @Author szw * @Date 2020/2/13 18:06 * @Version 1.0 **/ @Configuration public class ThreadPoolConfig { /** * 核心线程池大小 */ private final int CORE_POOL_SIZE = 50; /** * 最大可创建的线程数 */ private final int MAX_POOL_SIZE = 200; /** * 队列最大长度 */ private final int QUEUE_CAPACITY = 1000; /** * 线程池维护线程所允许的空闲时间 */ private final int KEEP_ALIVE_SECONDS = 300; @Bean(name = "threadPoolTaskExecutor") public ThreadPoolTaskExecutor threadPoolTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setMaxPoolSize(CORE_POOL_SIZE); executor.setCorePoolSize(MAX_POOL_SIZE); executor.setQueueCapacity(QUEUE_CAPACITY); executor.setKeepAliveSeconds(KEEP_ALIVE_SECONDS); // 线程池对拒绝任务(无线程可用)的处理策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); return executor; } /** * 执行周期性或定时任务 */ @Bean(name = "scheduledExecutorService") protected ScheduledExecutorService scheduledExecutorService() { return new ScheduledThreadPoolExecutor(CORE_POOL_SIZE, new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build()) { @Override protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); Threads.printException(r, t); } }; } }
异步任务管理器
import com.jarvis.utils.SpringContextHolder; import com.jarvis.utils.Threads; import java.util.TimerTask; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * 异步任务管理器 * * @Author szw * @Date 2020/2/13 18:06 * @Version 1.0 **/ public class AsyncManager { /** * 操作延迟10毫秒 */ private final int OPERATE_DELAY_TIME = 10; /** * 异步操作任务调度线程池 */ private ScheduledExecutorService executor = SpringContextHolder.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 com.jarvis.api.observatory.entity.LoginInfor; import com.jarvis.api.observatory.service.impl.LoginInforServiceImpl; import com.jarvis.constants.Constants; import com.jarvis.utils.*; import eu.bitwalker.useragentutils.UserAgent; import lombok.extern.slf4j.Slf4j; import java.util.TimerTask; /** * 异步工厂(产生任务用) * * @Author szw * @Date 2020/2/17 15:16 * @Version 1.0 **/ @Slf4j public class AsyncFactory { /** * 记录登陆信息 * * @param username 用户名 * @param status 状态 * @param message 消息 * @param args 列表 * @return 任务task */ public static TimerTask recordLoginInfor(final String username, final String status, final String message, final Object... args) { final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); final String ip = HttpContextUtils.getHttpServletRequest().getRemoteAddr(); return new TimerTask() { @Override public void run() { String address = AddressUtils.getRealAddressByIP(ip); StringBuilder s = new StringBuilder(); s.append(LogUtils.getBlock(ip)); s.append(address); s.append(LogUtils.getBlock(username)); s.append(LogUtils.getBlock(status)); s.append(LogUtils.getBlock(message)); // 打印信息到日志 log.info(s.toString(), args); // 获取客户端操作系统 String os = userAgent.getOperatingSystem().getName(); // 获取客户端浏览器 String browser = userAgent.getBrowser().getName(); // 封装对象 LoginInfor logininfor = new LoginInfor(); logininfor.setLoginName(username); logininfor.setIpAddr(ip); logininfor.setLoginLocation(address); logininfor.setBrowser(browser); logininfor.setOs(os); logininfor.setMsg(message); // 日志状态 if (Constants.LOGIN_SUCCESS.equals(status) || Constants.LOGOUT.equals(status)) { logininfor.setStatus(Constants.SUCCESS); } else if (Constants.LOGIN_FAIL.equals(status)) { logininfor.setStatus(Constants.FAIL); } // 插入数据 SpringUtils.getBean(LoginInforServiceImpl.class).insertLoginInfor(logininfor); } }; } }
使用
AsyncManager.me().execute(AsyncFactory.recordLoginInfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked")));