私はSpringで非同期タスクを実行するのが初めてなので、これがばかげた質問のように聞こえるかどうかを許してください。
@AsyncアノテーションがメソッドレベルでSpring 3.x以降に導入され、そのメソッドの呼び出しが非同期に発生することを読みました。また、Spring構成ファイルでThreadPoolTaskExecutorを構成できることも読みました。
私が理解できないのは、takエグゼキューターから@Asyncアノテーション付きメソッドを呼び出す方法が想定していることです-AsyncTaskExecutor
以前はクラスで次のようなことをしていました:
@Autowired protected AsyncTaskExecutor executor;
その後
executor.submit(<Some Runnable or Callable task>)
@Asyncアノテーション付きメソッドとTaskExecutorの関係を理解できません。
インターネットでたくさん検索してみましたが何も見つかりませんでした。
誰かが同じ例を提供できますか?.
@Async
の使用例を次に示します。
@Async
void doSomething() {
// this will be executed asynchronously
}
別のクラスからそのメソッドを呼び出すと、非同期に実行されます。戻り値が必要な場合は、Future
を使用してください
@Async
Future<String> returnSomething(int i) {
// this will be executed asynchronously
}
@Async
とTaskExecutor
の関係は、@Async
が裏でTaskExecutor
を使用することです。ドキュメントから:
メソッドで@Asyncを指定する場合、デフォルトでは、使用されるエグゼキューターは、前述の「annotation-driven」要素に提供されるものです。ただし、特定のメソッドを実行するときにデフォルト以外のエグゼキューターを使用する必要があることを示す必要がある場合は、@ Asyncアノテーションのvalue属性を使用できます。
デフォルトのエグゼキューターを設定するには、これをあなたの春の設定に追加します
<task:annotation-driven executor="myExecutor" />
または、特定のエグゼキューターを使い捨てに使用するには
@Async("otherExecutor")
完全な例
構成スプリング
@Configuration
@EnableAsync
@ComponentScan("com.async")
public class AppConfig {
@Bean
public AsyncManager asyncManger() {
return new AsyncManager();
}
@Bean
public AsyncExecutor asyncExecutor() {
return new AsyncExecutor();
}
}
Executorクラスが作成されました。Executoriは、Springがスレッド管理を処理するように作成しました。
public class AsyncExecutor extends AsyncConfigurerSupport {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("Violation-");
executor.initialize();
return executor;
}
}
マネージャーを作成します。
public class AsyncManager {
@Autowired
private AsyncService asyncService;
public void doAsyncTask(){
try {
Map<Long, ViolationDetails> violation = asyncService.getViolation();
if(!org.springframework.util.CollectionUtils.isEmpty(violation)){
violation.entrySet().forEach( violationEntry -> {System.out.println(violationEntry.getKey() +"" +violationEntry.getValue());});
}
System.out.println("do some async task");
} catch (Exception e) {
}
}
}
サービスクラスを設定します。
@Service
public class AsyncService {
@Autowired
private AsyncExecutor asyncExecutor;
@Async
public Map<Long,ViolationDetails> getViolation() {
// TODO Auto-generated method stub
List<Long> list = Arrays.asList(100l,200l,300l,400l,500l,600l,700l);
Executor executor = asyncExecutor.getAsyncExecutor();
Map<Long,ViolationDetails> returnMap = new HashMap<>();
for(Long estCode : list){
ViolationDetails violationDetails = new ViolationDetails(estCode);
returnMap.put(estCode, violationDetails);
executor.execute((Runnable)new ViolationWorker(violationDetails));
}
return returnMap;
}
}
class ViolationWorker implements Runnable{
private ViolationDetails violationDetails;
public ViolationWorker(ViolationDetails violationDetails){
this.violationDetails = violationDetails;
}
@Override
public void run() {
violationDetails.setViolation(System.currentTimeMillis());
System.out.println(violationDetails.getEstablishmentID() + " " + violationDetails.getViolation());
}
}
モデル。
public class ViolationDetails {
private long establishmentID;
private long violation;
public ViolationDetails(long establishmentID){
this.establishmentID = establishmentID;
}
public long getEstablishmentID() {
return establishmentID;
}
public void setEstablishmentID(long establishmentID) {
this.establishmentID = establishmentID;
}
public long getViolation() {
return violation;
}
public void setViolation(long violation) {
this.violation = violation;
}
}
実行するテスト
public class AppTest {
public static void main(String[] args) throws SQLException {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class);
ctx.refresh();
AsyncManager task= ctx.getBean(AsyncManager.class);
task.doAsyncTask();
}
}
設定ファイルでは、スレッドプール名のアノテーションドリブンタスクと、@ Async(プール名)のメソッドがそのプールの一部として実行されることに言及する必要があります。 @Asyncアノテーションを持つプロキシクラスを作成し、それをすべてのスレッドに対して実行します。
@Asyncをメソッドに追加し、以下をアプリケーションコンテキストに追加できます。
<task:annotation-driven executor="asynExecutor"/>
<task:executor id="asynExecutor" pool-size="5" />