被Chrome的高级特性折腾了一上午
早上起来修改了一个小程序,使用Jetty嵌入的方式写了一个Servlet。因为第一次使用Jetty,不太熟悉对Servlet的多线程的处理方式。写了一个简单的测试代码:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //log.info("process thread:" + Thread.currentThread().getId() + "\tname:" + Thread.currentThread().getName()); log.info("process thread:" + Thread.currentThread().getId() + "\tname:" + Thread.currentThread().getName()); try{ log.info("Sleep sevlet:" + this.hashCode()); Thread.sleep(1000 * 20); }catch(Exception e){ } }
Jetty的启动部分:
Server server = new Server(httpPort); System.out.println("Listening HTTP port:" + httpPort); ServletHandler handler=new ServletHandler(); server.setHandler(handler); handler.addServletWithMapping("org.socialnet.servlet.StatusServlet", "/test1/*"); handler.addServletWithMapping("org.socialnet.servlet.StatusServlet", "/test2/*"); server.start(); server.join(); System.out.println("Shutdown HTTP service..");
打开我的Chrome,在两个不同的标签页里面输入:
http://127.0.0.1:8081/test1,
按理说应该出现2个,“Sleep sevlet: xxx” 的信息。因为Sevlet是多线程的。 但是事实上并没有同时出现2个Sleep的线程。而是一个Sleep结束后,才出现另外一个Sleep servelt.
这个时候可能很多人第一反应就是,Jetty的线程池大小不足,或者是单线程在处理请求。我觉得这种想法是合理的,本来Jetty就是轻量级的Server. 使用单线程来处理请求也没有什么不可以。为了验证这想法,修改了一下Jetty的启动部分:
Server server = new Server(httpPort); System.out.println("Listening HTTP port:" + httpPort); ServletHandler handler=new ServletHandler(); server.setHandler(handler); handler.addServletWithMapping("org.socialnet.servlet.StatusServlet", "/test1/*"); handler.addServletWithMapping("org.socialnet.servlet.StatusServlet", "/test2/*"); server.start(); log.info("thread:" + server.getThreadPool().getThreads() + "\tidle:" + server.getThreadPool().getIdleThreads()); server.join(); System.out.println("Shutdown HTTP service..");
输出活动线程的数量,果然和我期望一样,“thread:1 tidle:0” 只有一个服务线程启动了。马上google/ baidu 查询增加线程数量的方式。由于都要引入额外的包。我决定自己写一个简单的线程池,代码如下:
ThreadPool pool = new ThreadPool(){ @Override public boolean dispatch(final Runnable arg0) { log.info new Thread(){ public void run(){ arg0.run(); } }.start(); return true; } .... };
对于每一个新的任务都启动一个新的线程,这下总可以了吧。 启动服务器。还是在多个标签窗口中刷新 " http://127.0.0.1:8081/test1" 还是没有按我期望的那样同时出现多个“Sleep servelt" 都是每隔20多秒出现一个"Sleep servelt" 感觉Sevlet就是在单线程运行一样。继续查看Jetty的API Doc. 说什么ServletHandler 不是完整的Sevelt的实现,有些限制,需要运行在Context里面才能是完整的Sevlet实现。 修改了代码
测试,还是如此。
后来试了以下在不同的标签打开:
http://127.0.0.1:8081/test1,
http://127.0.0.1:8081/test2,
这下出现了2个”Sleep servlt"了。但是无论我怎么增加线程,和在不同的标签页刷新,Sevelet总是串行的运行。实在是没有办法了,只好修改线程池,把运行的线程都输出看阻塞在什么地方了。最后发现一个问题,无论在多少个标签中刷新:
http://127.0.0.1:8081/test1。 都只会有一个TCP连接在线程池里面。原来Chrome对相同的URL,在不同 的标签打开只会连立一个连接。换成IE测试了一下,每次刷新都会出现一个新的Connection.
折腾了一上午,原来是Chrome的高级特性。