java中的Select的异常处理

web容器会为每个请求分配一个线程,Servlet3.0新增了异步处理,解决多个线程不释放占据内存的问题。可以先释放容器分配给请求的线程与相关资源,减轻系统负担,原先释放了容器所分配线程的请求,其响应将被延后,可以在处理完成后再对客户端进行响应。

一、AsyncContex简介

为了支持异步处理,在ServletRequest上提供了startAsync()方法。可以通过AsyncContext的getRequest()和getResponse()方法取得请求、响应对象,此次对客户端的响应将暂缓至调用AsyncContext的complete()或dispatch()方法为止。

首先要告知此容器支持Servlet异步处理,如:1: @WebServlet(urlPatterns="/some.do", asyncSupported = true)2: public class AsyncServlet extends HttpServlet{3:4: }

例1:异步处理的例子

AsyncServlet.java1: package ServletAPI;2:3: import java.io.IOException;4: import java.util.concurrent.ExecutorService;5: import java.util.concurrent.Executors;6: import javax.servlet.AsyncContext;7: import javax.servlet.ServletException;8: import javax.servlet.annotation.WebServlet;9: import javax.servlet.http.HttpServlet;10: import javax.servlet.http.HttpServletRequest;11: import javax.servlet.http.HttpServletResponse;12:13: /**14: * Servlet implementation class AsyncServlet15: */16: @WebServlet(name = "AsyncServlet", urlPatterns = { "/async.do" },asyncSupported=true)17: public class AsyncServlet extends HttpServlet {18: private static final long serialVersionUID = 1L;19: private ExecutorService executorService=Executors.newFixedThreadPool(10);20: /**21: * @see HttpServlet#HttpServlet()22: */23: public AsyncServlet() {24: super();25: // TODO Auto-generated constructor stub26: }27:28: /**29: * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)30: */31: protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {32: // TODO Auto-generated method stub33: response.setContentType("text/html;charset=UTF-8");34: AsyncContext ctx=request.startAsync();//开始异步处理,释放请求线程35: executorService.submit(new AsynvRequest(ctx)); //创建AsyncRequest,调度线程36:37: }38:39: /**40: * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)41: */42: protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {43: // TODO Auto-generated method stub44: }45: public void destroy(){46: executorService.shutdown();//关闭线程池47: }48:49: }50:

首先告诉容器,这个Servlet支持异步处理,对于每个请求,Servlet会取得其AsyncContext,并释放容器所分配的线程,响应被延迟后。对于这些被延迟后响应的请求,创建一个实现Runnable接口的AsyncRequest对象,并将其调度一个固定数量的线程池,让这些必须长时间处理的请求,在线程池中完成,不用每次分配线程。

例2:AsyncRequest是个实现Runnable的类,其模拟了长时间处理。

AsyncRequest.java1: package ServletAPI;2:3: import java.io.PrintWriter;4: import javax.servlet.AsyncContext;5: public class AsynvRequest implements Runnable{6: private AsyncContext ctx;7:8: public AsynvRequest(AsyncContext ctx) {9: super();10: this.ctx = ctx;11: }12:13: @Override14: public void run() {15: // TODO Auto-generated method stub16: try {17: Thread.sleep(10000);//模拟冗长请求18: PrintWriter out=ctx.getResponse().getWriter();19: out.println("久等了...XD");//输出结果20: ctx.complete();//对客户端完成响应21: } catch (Exception e) {22: // TODO Auto-generated catch block23: throw new RuntimeException(e);24: }25:26: }27:28: }29:

以暂停线程的方式来模拟长时间处理,并输出简单的文字,最后调用complete()对客户端完成响应。

二、模拟服务器推播

HTTP是基于请求、响应模型,如果客户端要获得服务器的最新状态,就必须以定期方式发送请求,查询服务器端的最新状态。

Servlet 3.0提供的异步处理技术,可以解决每个请求占用线程的问题,再结合Ajax异步请求技术,就可以达到类似服务器主动通知浏览器的行为。这就是所谓的服务器端推播。

例3:模拟应用程序不定期产生最新数据,这个部分由实现ServletContextListener的类负责,会在程序启动时进行。

WebInitListener.java1: package ServletAPI;2:3: import java.util.ArrayList;4: import java.util.List;5: import javax.servlet.AsyncContext;6: import javax.servlet.ServletContextEvent;7: import javax.servlet.ServletContextListener;8: import javax.servlet.annotation.WebListener9:10: /**11: * Application Lifecycle Listener implementation class WebInitListener12: *13: */14: @WebListener15: public class WebInitListener implements ServletContextListener {16: private List asyncs=new ArrayList<>();//所有的异步请求AsyncContext将存储在这个List中。17:18: public void contextDestroyed(ServletContextEvent arg0) {19: // TODO Auto-generated method stub20: }21:22: /**23: * @see ServletContextListener#contextInitialized(ServletContextEvent)24: */25: public void contextInitialized(ServletContextEvent arg0) {26: // TODO Auto-generated method stub27: new Thread(new Runnable(){28: public void run(){29: while(true){30: try {//模拟产生随机数字31: Thread.sleep((int)(Math.random()*10000));32: double num=Math.random()*10;33: synchronized (asyncs) {34: for(AsyncContext ctx:asyncs){35: ctx.getResponse().getWriter().println(num);36: ctx.complete();37: }38: }39: } catch (Exception e) {40: // TODO Auto-generated catch block41: throw new RuntimeException();42: }43: }44: }45: }).start();46: }47:48: }49:

有个List会存储所有的异步请求的AsyncContext,并在不定时产生数字后,逐一对客户端响应,并调用AsyncContext的conmplete()来完成请求。

负责接收请求的Servlet,一收到请求,就将之加入到List中。

AsyncNumServlet.java1: package ServletAPI;2:3: import java.io.IOException;4: import java.util.List;5: import javax.servlet.AsyncContext;6: import javax.servlet.ServletException;7: import javax.servlet.annotation.WebServlet;8: import javax.servlet.http.HttpServlet;9: import javax.servlet.http.HttpServletRequest;10: import javax.servlet.http.HttpServletResponse;11:12: @WebServlet(name = "AsyncNumServlet", urlPatterns = { "/asyncNum.do" }, asyncSupported=true)13: public class AsyncNumServlet extends HttpServlet {14: private static final long serialVersionUID = 1L;15: private List asyncs;16:17: public void init() throws ServletException{18: asyncs=(List)getServletContext().getAttribute("asyncs");19:20: }21: /**22: * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)23: */24: protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {25: // TODO Auto-generated method stub26: AsyncContext ctx=request.startAsync();//开始异步处理27: synchronized (asyncs) {28: asyncs.add(ctx);//加入维护AsyncContext的List中29: }30: }31:32: }33:

由于List是储存为ServletContext属性,所以在Servlet中,必须从ServletContext中取出,每次请求到来时,调用HttpServletRequest的startAsync()进行异步处理,并取得AsyncContext加入维护AsyncContext的List中。

可以使用一个简单的HTML,使用Ajax技术,发送异步请求值服务器端,这个请求会被延迟,直到服务器端完成响应后,更新网页上的资料,并再度发送异步请求:

async.html1: 2: 3:

4: 5: 实时资料6: 28: 29: 30: 实时资料: 031: 32:

可以试着用多个浏览器请求这个页面,会看到每个浏览器的资料是同步的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值