我有2个同步方法,下面的方法没有阻止。
@RequestMapping("/send1")
@Async
public Future<Boolean> sendMail() throws InterruptedException {
System.out.println("sending mail 1..-"
+ Thread.currentThread().getName());
Thread.sleep(1000 * 16);
System.out.println("sending mail 1 completed");
return new AsyncResult<Boolean>(true);
}
但以下一个阻止。
@RequestMapping("/send3")
public void callAsyn3() throws InterruptedException, ExecutionException {
Future<Boolean> go = sendMail3("test");
}
@Async
public Future<Boolean> sendMail3(String msg) throws InterruptedException {
boolean acceptedYet = false;
Thread.sleep(1000 * 12);
if (!msg.equalsIgnoreCase("")) {
acceptedYet = true;
}
return new AsyncResult<>(acceptedYet);
}
它们属于同一个控制器类,为什么会出现这种不同的行为?
答案 0 :(得分:1)
在第二种情况下,您调用内部方法。所以忽略@Async(不调用代理方法)。
有两种方法可以修复
第一个是引入一个单独的bean(例如MyService)并在那里移动带有@Async
方法的注释。
第二种方法是将控制器自动装配
@Controller 公共类MyController {
@Autowired
private MyController myController;
@RequestMapping("/send3")
public void callAsyn3() throws InterruptedException, ExecutionException {
Future<Boolean> go = myController.sendMail3("test");
}
@Async
public Future<Boolean> sendMail3(String msg) throws InterruptedException {
boolean acceptedYet = false;
Thread.sleep(1000 * 12);
if (!msg.equalsIgnoreCase("")) {
acceptedYet = true;
}
return new AsyncResult<>(acceptedYet);
}
答案 1 :(得分:1)
同一类中的调用方法不会通过代理。因此,您不能在同一个类中使用@Async
的方法,并使调用异步。
我们可以创建另一个服务并在那里编写@Async
方法。像这样的东西
@Service
public class MyService {
@Async
public Future<Boolean> sendMail3(String msg) throws InterruptedException {
boolean acceptedYet = false;
Thread.sleep(1000 * 12);
if (!msg.equalsIgnoreCase("")) {
acceptedYet = true;
}
return new AsyncResult<>(acceptedYet);
}
}
这将以异步方式运行(非阻塞)。
如果要在同一个控制器中执行此操作,可以手动将其提交到某个线程池。
答案 2 :(得分:1)
你有自我调用,直接从方法callAsyn3调用方法sendMail3。它不起作用,因为它绕过代理并直接调用底层方法。 简单修复 - 您应该从上下文获取控制器并从此实例调用callAsyn3。 正常修复 - 创建新服务 - asyncSendMailComponent / Service,将sendMail3移动到asyncSendMailComponent,将asyncSendMailComponent注入您的控制器并调用sendMail3
控制器中的:
@Autowired
private AsyncSendMailComponent asyncSendMailComponent;
@RequestMapping("/send3")
public void callAsyn3() throws InterruptedException, ExecutionException {
Future<Boolean> go = asyncSendMailComponent.sendMail3(msg)
}
异步服务
@Service
pubclic class AsyncSendMailComponent {
@Async
public Future<Boolean> sendMail3(String msg) throws InterruptedException {
boolean acceptedYet = false;
Thread.sleep(1000 * 12);
if (!msg.equalsIgnoreCase("")) {
acceptedYet = true;
}
return new AsyncResult<>(acceptedYet);
}
}