1、任務執行和調度
spring用taskexecutor和taskscheduler接口提供了異步執行和調度任務的抽象。
spring的taskexecutor和java.util.concurrent.executor接口時一樣的,這個接口只有一個方法execute(runnable task)。
1.1、taskexecutor類型
spring已經內置了許多taskexecutor的實現,你沒有必要自己去實現:
- simpleasynctaskexecutor 這種實現不會重用任何線程,每次調用都會創建一個新的線程。
- synctaskexecutor 這種實現不會異步的執行
- concurrenttaskexecutor 這種實現是java.util.concurrent.executor的一個adapter。
- simplethreadpooltaskexecutor 這種實現實際上是quartz的simplethreadpool的一個子類,它監聽spring的聲明周期回調。
- threadpooltaskexecutor 這是最常用最通用的一種實現。它包含了java.util.concurrent.threadpoolexecutor的屬性,并且用taskexecutor進行包裝。
1.2、注解支持調度和異步執行
to enable support for @scheduled and @async annotations add @enablescheduling and @enableasync to one of your
1
2
3
4
5
6
7
|
@configuration classes: @configuration @enableasync @enablescheduling public class appconfig { } |
特別注意
the default advice mode for processing @async annotations is "proxy" which allows for interception of calls through the proxy only; local calls within the same class cannot get intercepted that way. for a more advanced mode of interception, consider switching to "aspectj" mode in combination with compile-time or load-time weaving.
默認是用代理去處理@async的,因此,相同類中的方法調用帶@async的方法是無法異步的,這種情況仍然是同步。
舉個例子:下面這種,在外部直接調用sayhi()是可以異步執行的,而調用sayhello()時sayhi()仍然是同步執行
1
2
3
4
5
6
7
8
9
10
|
public class a { public void sayhello() { sayhi(); } @async public void sayhi() { } } |
1.3、@async注解
在方法上加@async注解表示這是一個異步調用。換句話說,方法的調用者會立即得到返回,并且實際的方法執行是想spring的taskexecutor提交了一個任務。
in other words, the caller will return immediately upon invocation and the actual execution of the method will occur in a task that has been submitted to a spring taskexecutor.
1
2
3
4
|
@async void dosomething() { // this will be executed asynchronously } |
1
2
3
4
|
@async void dosomething(string s) { // this will be executed asynchronously } |
1
2
3
4
|
@async future<string> returnsomething( int i) { // this will be executed asynchronously } |
注意:
@async methods may not only declare a regular java.util.concurrent.future return type but also spring's org.springframework.util.concurrent.listenablefuture or, as of spring 4.2, jdk 8's java.util.concurrent.completablefuture: for richer interaction with the asynchronous task and for immediate composition with further processing steps.
1.4、@async限定executor
默認情況下,當在方法上加@async注解時,將會使用一個支持注解驅動的executor。然而,@async注解的value值可以指定一個別的executor
1
2
3
4
|
@async ( "otherexecutor" ) void dosomething(string s) { // this will be executed asynchronously by "otherexecutor" } |
這里,otherexecutor是spring容器中任意executor bean的名字。
1.5、@async異常管理
當一個@async方法有一個future類型的返回值時,就很容易管理在調future的get()方法獲取任務的執行結果時拋出的異常。如果返回類型是void,那么異常是不會被捕獲到的。
1
2
3
4
5
6
7
|
public class myasyncuncaughtexceptionhandler implements asyncuncaughtexceptionhandler { @override public void handleuncaughtexception(throwable ex, method method, object... params) { // handle exception } } |
2、線程池配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; import org.springframework.scheduling.annotation.enableasync; import org.springframework.scheduling.concurrent.threadpooltaskexecutor; @configuration @enableasync public class taskexecutorconfig { private integer corepoolsize = 30 ; private integer maxpoolsize = 50 ; private integer keepaliveseconds = 300 ; // private integer queuecapacity = 2000; @bean ( "mythreadpooltaskexecutor" ) public threadpooltaskexecutor mythreadpooltaskexecutor() { threadpooltaskexecutor executor = new threadpooltaskexecutor(); executor.setcorepoolsize(corepoolsize); executor.setmaxpoolsize(maxpoolsize); executor.setkeepaliveseconds(keepaliveseconds); // executor.setqueuecapacity(queuecapacity); executor.setwaitfortaskstocompleteonshutdown( true ); executor.initialize(); return executor; } } |
調用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
@async ( "mythreadpooltaskexecutor" ) @override public void present(couponpresentlogentity entity) { try { couponbaseresponse rst = couponsendrpcservice.send(entity.getuserid(), entity.getcouponbatchkey(), "1" , entity.getvendorid()); if ( null != rst && rst.issuccess()) { entity.setstatus(presentstatusenum.success.gettype()); } else { string reason = ( null == rst) ? "響應異常" : rst.getmsg(); entity.setfailurereason(reason); entity.setstatus(presentstatusenum.failure.gettype()); } } catch (exception ex) { log.error(ex.getmessage(), ex); entity.setfailurereason(ex.getmessage()); entity.setstatus(presentstatusenum.failure.gettype()); } couponpresentlogdao.update(entity); } |
結果
[info ] 2018-05-09 16:27:39.887 [mythreadpooltaskexecutor-1] [com.ourhours.coupon.rpc.dubbo.receivelogfilter] - receive method-name:send; arguments:[10046031,"4d7cc32f8f7e4b00bca56f6bf4b3b658","1",10001]
[info ] 2018-05-09 16:27:39.889 [mythreadpooltaskexecutor-2] [com.ourhours.coupon.rpc.dubbo.receivelogfilter] - receive method-name:send; arguments:[10046031,"4d7cc32f8f7e4b00bca56f6bf4b3b658","1",10001]
參考:
spring framework reference documentation 4.3.17.release
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://www.cnblogs.com/cjsblog/p/9016657.html