原文连接:www.cnblogs.com/baixianlong…html
特色:nginx
能够先释放容器分配给请求的线程与相关资源,减轻系统负担,释放了容器所分配线程的请求,其响应将被延后,能够在耗时处理完成(例如长时间的运算)时再对客户端进行响应。程序员
@RequestMapping(value = "/email/servletReq", method = GET)
public void servletReq (HttpServletRequest request, HttpServletResponse response) {
AsyncContext asyncContext = request.startAsync();
//设置监听器:可设置其开始、完成、异常、超时等事件的回调处理
asyncContext.addListener(new AsyncListener() {
@Override
public void onTimeout(AsyncEvent event) throws IOException {
System.out.println("超时了...");
//作一些超时后的相关操做...
}
@Override
public void onStartAsync(AsyncEvent event) throws IOException {
System.out.println("线程开始");
}
@Override
public void onError(AsyncEvent event) throws IOException {
System.out.println("发生错误:"+event.getThrowable());
}
@Override
public void onComplete(AsyncEvent event) throws IOException {
System.out.println("执行完成");
//这里能够作一些清理资源的操做...
}
});
//设置超时时间
asyncContext.setTimeout(20000);
asyncContext.start(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(10000);
System.out.println("内部线程:" + Thread.currentThread().getName());
asyncContext.getResponse().setCharacterEncoding("utf-8");
asyncContext.getResponse().setContentType("text/html;charset=UTF-8");
asyncContext.getResponse().getWriter().println("这是异步的请求返回");
} catch (Exception e) {
System.out.println("异常:"+e);
}
//异步请求完成通知
//此时整个请求才完成
asyncContext.complete();
}
});
//此时之类 request的线程链接已经释放了
System.out.println("主线程:" + Thread.currentThread().getName());
}复制代码
@RequestMapping(value = "/email/callableReq", method = GET)
@ResponseBody
public Callable<String> callableReq () {
System.out.println("外部线程:" + Thread.currentThread().getName());
return new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(10000);
System.out.println("内部线程:" + Thread.currentThread().getName());
return "callable!";
}
};
}
@Configuration
public class RequestAsyncPoolConfig extends WebMvcConfigurerAdapter {
@Resource
private ThreadPoolTaskExecutor myThreadPoolTaskExecutor;
@Override
public void configureAsyncSupport(final AsyncSupportConfigurer configurer) {
//处理 callable超时
configurer.setDefaultTimeout(60*1000);
configurer.setTaskExecutor(myThreadPoolTaskExecutor);
configurer.registerCallableInterceptors(timeoutCallableProcessingInterceptor());
}
@Bean
public TimeoutCallableProcessingInterceptor timeoutCallableProcessingInterceptor() {
return new TimeoutCallableProcessingInterceptor();
}复制代码
}web
@RequestMapping(value = "/email/webAsyncReq", method = GET)
@ResponseBody
public WebAsyncTask<String> webAsyncReq () {
System.out.println("外部线程:" + Thread.currentThread().getName());
Callable<String> result = () -> {
System.out.println("内部线程开始:" + Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(4);
} catch (Exception e) {
// TODO: handle exception
}
logger.info("副线程返回");
System.out.println("内部线程返回:" + Thread.currentThread().getName());
return "success";
};
WebAsyncTask<String> wat = new WebAsyncTask<String>(3000L, result);
wat.onTimeout(new Callable<String>() {
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
return "超时";
}
});
return wat;
}复制代码
@RequestMapping(value = "/email/deferredResultReq", method = GET)
@ResponseBody
public DeferredResult<String> deferredResultReq () {
System.out.println("外部线程:" + Thread.currentThread().getName());
//设置超时时间
DeferredResult<String> result = new DeferredResult<String>(60*1000L);
//处理超时事件 采用委托机制
result.onTimeout(new Runnable() {
@Override
public void run() {
System.out.println("DeferredResult超时");
result.setResult("超时了!");
}
});
result.onCompletion(new Runnable() {
@Override
public void run() {
//完成后
System.out.println("调用完成");
}
});
myThreadPoolTaskExecutor.execute(new Runnable() {
@Override
public void run() {
//处理业务逻辑
System.out.println("内部线程:" + Thread.currentThread().getName());
//返回结果
result.setResult("DeferredResult!!");
}
});
return result;
}复制代码
异步请求的处理。除了异步请求,通常上咱们用的比较多的应该是异步调用。一般在开发过程当中,会遇到一个方法是和实际业务无关的,没有紧密性的。好比记录日志信息等业务。这个时候正常就是启一个新线程去作一些业务处理,让主线程异步的执行其余业务。spring
代码略。。。就俩标签,本身试一把就能够了bash
调用的异步方法,不能为同一个类的方法(包括同一个类的内部类),简单来讲,由于Spring在启动扫描时会为其建立一个代理类,而同类调用时,仍是调用自己的代理类的,因此和日常调用是同样的。其余的注解如@Cache等也是同样的道理,说白了,就是Spring的代理机制形成的。因此在开发中,最好把异步服务单独抽出一个类来管理。下面会重点讲述。。服务器
其实咱们的注入对象都是从Spring容器中给当前Spring组件进行成员变量的赋值,因为某些类使用了AOP注解,那么实际上在Spring容器中实际存在的是它的代理对象。那么咱们就能够微信
@Controller
@RequestMapping("/app")
public class EmailController {
//获取ApplicationContext对象方式有多种,这种最简单,其它的你们自行了解一下
@Autowired
private ApplicationContext applicationContext;
@RequestMapping(value = "/email/asyncCall", method = GET)
@ResponseBody
public Map<String, Object> asyncCall () {
Map<String, Object> resMap = new HashMap<String, Object>();
try{
//这样调用同类下的异步方法是不起做用的
//this.testAsyncTask();
//经过上下文获取本身的代理对象调用异步方法
EmailController emailController = (EmailController)applicationContext.getBean(EmailController.class);
emailController.testAsyncTask();
resMap.put("code",200);
}catch (Exception e) {
resMap.put("code",400);
logger.error("error!",e);
}
return resMap;
}
//注意必定是public,且是非static方法
@Async
public void testAsyncTask() throws InterruptedException {
Thread.sleep(10000);
System.out.println("异步任务执行完成!");
}
}复制代码
代码实现,以下:并发
@Service
@Transactional(value = "transactionManager", readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public class EmailService {
@Autowired
private ApplicationContext applicationContext;
@Async
public void testSyncTask() throws InterruptedException {
Thread.sleep(10000);
System.out.println("异步任务执行完成!");
}
public void asyncCallTwo() throws InterruptedException {
//this.testSyncTask();
// EmailService emailService = (EmailService)applicationContext.getBean(EmailService.class);
// emailService.testSyncTask();
boolean isAop = AopUtils.isAopProxy(EmailController.class);//是不是代理对象;
boolean isCglib = AopUtils.isCglibProxy(EmailController.class); //是不是CGLIB方式的代理对象;
boolean isJdk = AopUtils.isJdkDynamicProxy(EmailController.class); //是不是JDK动态代理方式的代理对象;
//如下才是重点!!!
EmailService emailService = (EmailService)applicationContext.getBean(EmailService.class);
EmailService proxy = (EmailService) AopContext.currentProxy();
System.out.println(emailService == proxy ? true : false);
proxy.testSyncTask();
System.out.println("end!!!");
}
}复制代码
更多技术文章请关注微信公众号:Java程序员汇集地app