因爲公司須要收集移動端的操做事件,用戶的每個操做,都要存下來,咱們用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; } }