L'annotation @EnableAsync doit être ajoutée à l'application SpringBoot pour activer les appels asynchrones. Généralement, un pool de threads est configuré et la méthode asynchrone est transmise à un pool de threads spécifique pour être complétée, comme suit :
@Configuration @EnableAsync public class AsyncConfiguration { @Bean("doSomethingExecutor") public Executor doSomethingExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 核心线程数:线程池创建时候初始化的线程数 executor.setCorePoolSize(10); // 最大线程数:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程 executor.setMaxPoolSize(20); // 缓冲队列:用来缓冲执行任务的队列 executor.setQueueCapacity(500); // 允许线程的空闲时间60秒:当超过了核心线程之外的线程在空闲时间到达之后会被销毁 executor.setKeepAliveSeconds(60); // 线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池 executor.setThreadNamePrefix("do-something-"); // 缓冲队列满了之后的拒绝策略:由调用线程处理(一般是主线程) executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); executor.initialize(); return executor; } }
La méthode d'utilisation est très simple. Ajoutez l'annotation @Async aux méthodes qui nécessitent des méthodes asynchrones
@RestController public class AsyncController { @Autowired private AsyncService asyncService; @GetMapping("/open/something") public String something() { int count = 10; for (int i = 0; i < count; i++) { asyncService.doSomething("index = " + i); } return "success"; } } @Slf4j @Service public class AsyncService { // 指定使用beanname为doSomethingExecutor的线程池 @Async("doSomethingExecutor") public String doSomething(String message) { log.info("do something, message={}", message); try { Thread.sleep(1000); } catch (InterruptedException e) { log.error("do something error: ", e); } return message; } }
Accès : 127.0.0.1:8080/open/something, le journal est le suivant
06/02/2023 23:42 :42.486 INFO 21168 --- [io-8200-exec -17] x.g.b.system.controller.AsyncController : faire quelque chose se termine, durée 8 millisecondes
2023-02-06 23:42:42.488 INFO 21168 --- [ faire quelque chose -1] x.gits.boot.system.service. AsyncService : faire quelque chose, message=index = 0
2023-02-06 23:42:42.488 INFO 21168 --- [ do-something-5] x.gits. boot.system.service.AsyncService : faire quelque chose, message= index = 4
2023-02-06 23:42:42.488 INFO 21168 --- [ do-something-4] x.gits.boot.system.service.AsyncService : faire quelque chose, message=index = 3
2023-02 -06 23:42:42.488 INFO 21168 --- [ do-something-6] x.gits.boot.system.service.AsyncService : faire quelque chose, message=index = 5
2023-02-06 23:42:42.488 INFO 21168 --- [ do-something-9] x.gits.boot.system.service.AsyncService : faire quelque chose, message=index = 8
2023-02- 06 23:42:42.488 INFO 21168 --- [ do -something-8] x.gits.boot.system.service.AsyncService : faire quelque chose, message=index = 7
2023-02-06 23:42:42.488 INFO 21168 --- [do-something-10] x. gits.boot.system.service.AsyncService : faire quelque chose, message=index = 9
2023-02-06 23:42:42.488 INFO 21168 --- [ faire- quelque chose-7] x.gits.boot.system.service .AsyncService : faire quelque chose, message=index = 6
2023-02-06 23:42:42.488 INFO 21168 --- [ faire-quelque chose-2] x.gits .boot.system.service.AsyncService : faire quelque chose, message =index = 1
2023-02-06 23:42:42.488 INFO 21168 --- [ do-something-3] x.gits.boot.system.service. AsyncService : faire quelque chose, message=index = 2
On peut voir que l'effet de l'exécution asynchrone a été obtenu et que le pool de threads que nous avons configuré a été utilisé.
Lorsque la méthode asynchrone a une valeur de retour, comment obtenir le résultat de retour de l'exécution de la méthode asynchrone ? À ce stade, la méthode qui doit être appelée de manière asynchrone a la valeur de retour CompletableFuture.
CompletableFuture est une amélioration de Feature. Feature ne peut gérer que des tâches asynchrones simples, tandis que CompletableFuture peut effectuer des combinaisons complexes de plusieurs tâches asynchrones. Comme suit :
@RestController public class AsyncController { @Autowired private AsyncService asyncService; @SneakyThrows @ApiOperation("异步 有返回值") @GetMapping("/open/somethings") public String somethings() { CompletableFuture<String> createOrder = asyncService.doSomething1("create order"); CompletableFuture<String> reduceAccount = asyncService.doSomething2("reduce account"); CompletableFuture<String> saveLog = asyncService.doSomething3("save log"); // 等待所有任务都执行完 CompletableFuture.allOf(createOrder, reduceAccount, saveLog).join(); // 获取每个任务的返回结果 String result = createOrder.get() + reduceAccount.get() + saveLog.get(); return result; } } @Slf4j @Service public class AsyncService { @Async("doSomethingExecutor") public CompletableFuture<String> doSomething1(String message) throws InterruptedException { log.info("do something1: {}", message); Thread.sleep(1000); return CompletableFuture.completedFuture("do something1: " + message); } @Async("doSomethingExecutor") public CompletableFuture<String> doSomething2(String message) throws InterruptedException { log.info("do something2: {}", message); Thread.sleep(1000); return CompletableFuture.completedFuture("; do something2: " + message); } @Async("doSomethingExecutor") public CompletableFuture<String> doSomething3(String message) throws InterruptedException { log.info("do something3: {}", message); Thread.sleep(1000); return CompletableFuture.completedFuture("; do something3: " + message); } }
Interface d'accès
C:UsersAdministrator>curl -X GET "http://localhost:8080/open/something" -H "accepter : */*"
faire quelque chose1 : créer une commande ;
faire quelque chose2 : réduire le compte ;
faire quelque chose3 : enregistrer le journal
Les journaux de touches sur la console sont les suivants :
2023-02-06 00:27:42.238 INFO 5672 --- [ do-something-3] x .gits.boot .system.service.AsyncService : faire quelque chose3 : enregistrer le journal
2023-02-06 00:27:42.238 INFO 5672 --- [do-something-2] x.gits.boot.system.service.AsyncService : faire quelque chose2 : réduire le compte
2023-02-06 00:27:42.238 INFO 5672 --- [ do-something-1] x.gits.boot.system.service.AsyncService : faire quelque chose1 : créer une commande
@ Les annotations Async échoueront dans les scénarios suivants, ce qui signifie que l'annotation @Async est clairement utilisée, mais que le multithreading n'est pas utilisé.
Les méthodes asynchrones sont modifiées avec le mot-clé static ;
La classe asynchrone n'est pas un bean du conteneur Spring (généralement annoté @Component et @Service, et peut être analysée par Spring) ; disponible dans les applications SpringBoot Ajoutez l'annotation @EnableAsync ;
Dans la même classe, si une méthode appelle une autre méthode avec une annotation @Async, l'annotation ne prendra pas effet. La raison en est que la méthode annotée avec @Async est exécutée dans la classe proxy.
Il est à noter que : la valeur de retour d'une méthode asynchrone utilisant l'annotation @Async ne peut être que void ou Future et ses sous-classes. Lorsque le résultat renvoyé est d'un autre type, la méthode sera toujours exécutée de manière asynchrone, mais le. la valeur de retour sera nulle. Une partie du code source est la suivante :
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!