因为公司须要收集移动端的操做事件,用户的每个操做,都要存下来,咱们用mongodb存放操做日志。spring
这时能够用spring异步任务来处理,能够提快接口的响应时间。作法以下:mongodb
在spring的配置文件里面加入下面类容数据库
rejection-policy="DISCARD" 表示 pool-size到了最大,队列也满了,再来任务就直接丢弃,由于这是收集数据,能够丢一些,防止系统崩溃编程
<!-- 数据收集异步处理的线程池 --> <task:executor id="dcExecutor" pool-size="15-1000" queue-capacity="100" keep-alive="5" rejection-policy="DISCARD" /> <!-- 上下车提醒异步处理的线程池 --> <task:executor id="remind" pool-size="15-500" queue-capacity="1000" keep-alive="5" rejection-policy="DISCARD" />
要调用的方法上面加上注解@Asyncjson
@Async("dcExecutor") public void handleDataCollection(CMDEnum cmdEnum, String json) { switch (cmdEnum) { case ROUTE_DETAIL: RouteDetail routeDetail = JSON.parseObject(json, RouteDetail.class); save(routeDetail, cmdEnum.tableName()); break; case TRANSFER: Transfer transfer = JSON.parseObject(json, Transfer.class); save(transfer, cmdEnum.tableName()); break; default: break; }
@Async这个注解用于标注某个方法或某个类里面的全部方法都是须要异步处理的。被注解的方法被调用的时候,会在新线程中执行,而调用它的方法会在原来的线程中执行。这样能够避免阻塞、以及保证任务的实时性。适用于处理log、发送邮件、短信……等。异步
注解的应用范围:async
相关的配置:spa
<task:annotation-driven />配置:.net
例子:线程
<task:annotation-driven executor="asyncExecutor" />
<task:executor />配置参数:
配置例子:
<task:annotation-driven executor="asyncExecutor" /> <task:executor id="asyncExecutor" pool-size="100-10000" queue-capacity="10"/>
实例:
<!-- 缺省的异步任务线程池 --> <task:annotation-driven executor="asyncExecutor" /> <task:executor id="asyncExecutor" pool-size="100-20000" queue-capacity="10" /> <!-- 处理数据收集的线程池 --> <task:executor id="dcExecutor" pool-size="15-10000" queue-capacity="50" keep-alive="50/>
@Async("dcExecutor") //若是不指定名字,会使用缺省的“asyncExecutor” public void handleDataCollection(CMDEnum cmdEnum, String json) { switch (cmdEnum) { case ROUTE_DETAIL: RouteDetail routeDetail = JSON.parseObject(json, RouteDetail.class); save(routeDetail, cmdEnum.tableName()); break; case TRANSFER: Transfer transfer = JSON.parseObject(json, Transfer.class); save(transfer, cmdEnum.tableName()); break; default: break; }
(注意若是在同一个类中调用的话,不会生效,缘由请参考:
http://blog.csdn.net/clementad/article/details/47339519
线程的优先级和类型:
优先级:NORM_PRIORITY
类型:非守护线程
用户线程(User Thread):JVM会等待全部的用户线程结束后才退出;当系统中没有用户线程了,JVM也就退出了
守护线程(Daemon Thread):通常是为其余线程提供服务的线程,好比GC垃圾回收器;JVM退出时,不会管守护线程是否存在,而是直接退出
因此,对于文件、数据库的操做,不适宜使用守护线程,否则可能会丢失数据!
Web应用中止时,Spring容器会被关闭,调用者若是是Spring bean,就会中止生成新任务。然而,线程池中已经在运行的任务,因为缺省是用户线程,因此JVM会等待它们结束后才退出。
附:Java编程方式的配置方法:
@Configuration @EnableAsync public class SpringConfig { /** Set the ThreadPoolExecutor's core pool size. */ private int corePoolSize = 10; /** Set the ThreadPoolExecutor's maximum pool size. */ private int maxPoolSize = 200; /** Set the capacity for the ThreadPoolExecutor's BlockingQueue. */ private int queueCapacity = 10; private String ThreadNamePrefix = "MyLogExecutor-"; @Bean public Executor logExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(corePoolSize); executor.setMaxPoolSize(maxPoolSize); executor.setQueueCapacity(queueCapacity); executor.setThreadNamePrefix(ThreadNamePrefix); // rejection-policy:当pool已经达到max size的时候,如何处理新任务 // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } }