RTF*_*RTF 3 java multithreading tomcat servlets servlet-3.0
我的Java(Tomcat 8)Web服务器是否可以安全地生成线程以响应HTTP请求?我正在看帖子和论坛,有些人说这绝对没问题,其他人说不要这样做.
我的用例是这样的:
 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    ...
    ...
    final MyResult res = new MyResult();
    Thread first = new Thread(new Runnable() {
         @Override
         public void run() {
             // put this into res
         }
     });
     Thread second = new Thread(new Runnable() {
         @Override
         public void run() {
             // put that into res
         }
     });
     first.start();
     second.start();
     first.join(10000);
     second.join(10000);
     // return res
 }
当我说安全时,我的意思是关于Web服务器的稳定性,我提出的内容是否存在任何内在的危险.正如@Burrman指出的那样,线程池在这里是个好主意,我会这样做.如果我正在使用线程池,那么我应该关注或需要解决的servlet容器是否存在任何其他潜在问题?
我想我正在考虑的是,例如,JDBC连接.我相信建议使用JNDI资源等进行设置,并使用Tomcat配置进行配置.是否有必要或建议产生任意线程,如我的例子?
首先,它看起来你正在修改result两个线程中的对象.这不是线程安全的,因为这些first和second线程可能彼此不可见或者servlet正在运行的线程可见.有关详细信息,请参阅此文章.
其次,如果你在这些其他线程中修改响应,不,这将是不安全的.退出doGet方法后,您应该考虑发送的响应.在您的示例中,在这两个线程运行之前,响应将有可能被发送回客户端.
假设MyResult result影响response的对象(你要么加入result到response,它的影响的响应代码等).有几种方法可以解决这个问题.
使用ExecutorService和Future:
public void doGet(HttpServletRequest request, HttpServletResponse response) {
   // Creating a new ExecutorService for illustrative purposes.
   // As mentioned in comments, it is better to create a global 
   // instance of ExecutorService and use it in all servlets. 
   ExecutorService executor = Executors.newFixedThreadPool(2);
   Future<Result1> f1 = executor.submit(new Callable<Result1>() {
      @Override
       public Result1 call() throws Exception {
          // do expensive stuff here.
          return result;
      }
   });
   Future<Result2> f2 = executor.submit(new Callable<Result2>() {
      @Override
      public Result2 call() throws Exception {
         // do expensive stuff here.
         return result;
      }
   });
   // shutdown allows the executor to clean up its threads. 
   // Also prevents more Callables/Runnables from being submitted.
   executor.shutdown();
   // The call to .get() will block until the executor has
   // completed executing the Callable.
   Result1 r1 = f1.get();
   Result2 r2 = f2.get();
   MyResult result = new MyResult();
   // add r1 and r2 to result.
   // modify response based on result
}
更先进的技术是异步处理.如果您的请求需要很长时间来处理,则使用异步处理是一个好主意.它不会改善任何一个请求的延迟,但它确实允许Tomcat在任何给定的时间点处理更多请求.
一个简单的例子是:
@WebServlet(urlPatterns={"/asyncservlet"}, asyncSupported=true)
// Rather than @WebServlet, you can also specify these parameters in web.xml    
public class AsyncServlet extends HttpServlet {
   @Override
   public void doGet(HttpServletRequest request, HttpServletResponse response) {
      response.setContentType("text/html;charset=UTF-8");
      final AsyncContext acontext = request.startAsync();
      acontext.start(new Runnable() {
         public void run() {
            // perform time consuming steps here.
            acontext.complete();
   }
}
| 归档时间: | 
 | 
| 查看次数: | 3260 次 | 
| 最近记录: |