web-dev-qa-db-ja.com

Spring 3:@Asyncアノテーション付きメソッドをTaskExecutorから呼び出す方法

私はSpringで非同期タスクを実行するのが初めてなので、これがばかげた質問のように聞こえるかどうかを許してください。

@AsyncアノテーションがメソッドレベルでSpring 3.x以降に導入され、そのメソッドの呼び出しが非同期に発生することを読みました。また、Spring構成ファイルでThreadPoolTask​​Executorを構成できることも読みました。

私が理解できないのは、takエグゼキューターから@Asyncアノテーション付きメソッドを呼び出す方法が想定していることです-AsyncTaskExecutor

以前はクラスで次のようなことをしていました:

@Autowired protected AsyncTaskExecutor executor;

その後

executor.submit(<Some Runnable or Callable task>)

@Asyncアノテーション付きメソッドとTaskExecutorの関係を理解できません。

インターネットでたくさん検索してみましたが何も見つかりませんでした。

誰かが同じ例を提供できますか?.

12
tarares

@Asyncの使用例を次に示します。

@Async
void doSomething() {
    // this will be executed asynchronously
}

別のクラスからそのメソッドを呼び出すと、非同期に実行されます。戻り値が必要な場合は、Futureを使用してください

@Async
Future<String> returnSomething(int i) {
    // this will be executed asynchronously
}

@AsyncTaskExecutorの関係は、@Asyncが裏でTaskExecutorを使用することです。ドキュメントから:

メソッドで@Asyncを指定する場合、デフォルトでは、使用されるエグゼキューターは、前述の「annotation-driven」要素に提供されるものです。ただし、特定のメソッドを実行するときにデフォルト以外のエグゼキューターを使用する必要があることを示す必要がある場合は、@ Asyncアノテーションのvalue属性を使用できます。

デフォルトのエグゼキューターを設定するには、これをあなたの春の設定に追加します

<task:annotation-driven executor="myExecutor" />

または、特定のエグゼキューターを使い捨てに使用するには

@Async("otherExecutor")

http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/scheduling.html#scheduling-annotation-support-async を参照してください

30
Planky

完全な例

  1. 構成スプリング

    @Configuration        
    @EnableAsync        
    @ComponentScan("com.async")
    public class AppConfig {
    
        @Bean
        public AsyncManager asyncManger() {
            return new AsyncManager();
        }
    
        @Bean
        public AsyncExecutor asyncExecutor() {
            return new AsyncExecutor();
        }
    }
    
  2. 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;
        }
    }
    
  3. マネージャーを作成します。

    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) {
            }
    
        }
    }
    
  4. サービスクラスを設定します。

    @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());
        }
    }
    
  5. モデル。

    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;
        }
    
    }
    
  6. 実行するテスト

    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();
        }
    }
    
3
Kumar Abhishek

設定ファイルでは、スレッドプール名のアノテーションドリブンタスクと、@ Async(プール名)のメソッドがそのプールの一部として実行されることに言及する必要があります。 @Asyncアノテーションを持つプロキシクラスを作成し、それをすべてのスレッドに対して実行します。

1
user3631644

@Asyncをメソッドに追加し、以下をアプリケーションコンテキストに追加できます。

    <task:annotation-driven executor="asynExecutor"/>   
    <task:executor id="asynExecutor" pool-size="5" />
0
Lijo Monkuzhy