大型超市裡,通常都不止乙個收銀台,因為這樣可以提高效率,設想一下,如果某一天,其他的收銀員都請假了,只剩下乙個收銀台,看著那漫長的排隊大軍,是不是很捉急,很無奈。這就是非同步存在的意義了。
如果直接使用 @async,那麼預設就是使用******asynctaskexecutor執行緒池,由於 ******asynctaskexecutor 不限制併發執行緒而且不重用執行緒,那麼直接使用是有風險的,所以本章直接介紹通過自定義執行緒池來使用 @async 達到非同步呼叫的目的。
@enableasync
@configuration
public
class
threadpoolconfig
}
@enableasync註解主要是為了掃瞄範圍包下的所有@async註解
@component
public
class
asynctask
catch
(interruptedexception e)
system.out.
println
("task1 執行結束,耗時:"
+(system.
currenttimemillis()
- starttime));
}/**
* task 1
*/@async
("taskexecutor"
)public
void
task2()
catch
(interruptedexception e)
system.out.
println
("task2 執行結束,耗時:"
+(system.
currenttimemillis()
- starttime));
}}
@restcontroller
public
class
asynccontroller
}
列印結果:
test 開始執行
test 執行結束,耗時:6
task1 開始執行
task2 開始執行
task1 執行結束,耗時:1000
task2 執行結束,耗時:1000
以上的 task1 和 task2 任務是沒有返回值,如果碰到需要獲取任務結果怎麼辦,這時候就可以用到 future 了。
先給 task1 和 task2 新增返回值:
/**
* task 1
*/@async
("taskexecutor"
)public future
task1()
catch
(interruptedexception e)
system.out.
println
("task1 執行結束,耗時:"
+(system.
currenttimemillis()
- starttime));
return
newasyncresult
<
>
("task1 success");
}/**
* task 2
*/@async
("taskexecutor"
)public future
task2()
catch
(interruptedexception e)
system.out.
println
("task2 執行結束,耗時:"
+(system.
currenttimemillis()
- starttime));
return
newasyncresult
<
>
("task2 success");
}
然後進行呼叫,並獲取結果:
("/async"
)public
void
test()
throws executionexception, interruptedexception
列印結果如下:
test 開始執行
task1 開始執行
task2 開始執行
task1 執行結束,耗時:1001
task2 執行結束,耗時:1001
test 執行結果,result1:task1 success, result2:task2 success
test 執行結束,耗時:1016
可以看到 task1 和 task2 是非同步執行的,並且成功獲取到返回結果。
如果將在非同步任務類中直接呼叫 @async 修飾的方法,那麼非同步呼叫將會失效。
舉個栗子:
在 asynctask 類中直接呼叫 task1 和 task2 方法:
public
void
test()
然後在 asynccontroller 中呼叫 test 方法:
("/async"
)public
void
test()
列印結果如下:
test 開始執行
task1 開始執行
task1 執行結束,耗時:1000
task2 開始執行
task2 執行結束,耗時:1001
test 執行結束,耗時:2001
可以明顯看出,task1 和 task2 不是非同步執行的。原因就是呼叫 task1 和 task2 方法的是 asynctask 物件本身,而不是 spring 啟動的時候為其建立的**物件,沒有經過 spring 容器。如果要解決這個問題,就按照這個思路,建立乙個**物件即可。
@component
public
class
asynctask
/** * task 1
*/@async
("taskexecutor"
)public future
task1()
catch
(interruptedexception e)
system.out.
println
("task1 執行結束,耗時:"
+(system.
currenttimemillis()
- starttime));
return
newasyncresult
<
>
("task1 success");
}/**
* task 2
*/@async
("taskexecutor"
)public future
task2()
catch
(interruptedexception e)
system.out.
println
("task2 執行結束,耗時:"
+(system.
currenttimemillis()
- starttime));
return
newasyncresult
<
>
("task2 success");
}}
呼叫方法:
("/async"
)public
void
test()
throws executionexception, interruptedexception
列印結果:
test 開始執行
test 開始執行
test 執行結束,耗時:6
test 執行結束,耗時:0
task1 開始執行
task2 開始執行
task1 執行結束,耗時:1000
task2 執行結束,耗時:1000
可以看到 task1 和 task2 是非同步執行的,該思路是生效的。 框架 SpringBoot中自定義執行緒池
springboot中對執行緒池的自定義分為兩種 修改預設的執行緒池 建立新的自定義執行緒池 修改預設的執行緒池,需要建立配置類 加入兩個註解 enableasync開啟非同步執行功能 configurationspring配置類 實現asyncconfigurer介面,並實現兩個方法 public...
自定義Spring Boot裝配
spring boot自動配置會嘗試根據新增的jar依賴項自動配置spring應用程式。使用 componentscan 查詢您的bean 和使用 autowired 進行建構函式注入 自動配置類使用 conditionalonclass和 conditionalo singbean注釋,condi...
springboot自定義事務
1.在springboot專案中service的實現類可以通過註解 transactional新增事務 1.1 如果在service層用了try catch,在catch裡面再丟擲乙個 runtimeexception異常,這樣出了異常才會回滾 1.2你還可以直接在catch後面寫一句回滾 tran...