【问题标题】:Threadpool and request handling in TomcatTomcat 中的线程池和请求处理
【发布时间】:2014-11-16 04:27:15
【问题描述】:

好的,我已经问过一个关于此的问题,但需要更多信息。我会尽量与我的问题保持一致。 (因为我不确定这些概念)。

背景

我有一个 java web 项目(动态)。我正在编写 Restful 网络服务。下面是我班上的一个sn-p

/services
class Services{
 static DataSource ds;
 static{
 ds = createNewDataSource;
 }

 /serviceFirst
 @Consumes(Something)
 @produces(Something)
 public List<Data> doFirst(){
  Connection con = ds.getConnection();
  ResultSet res = con.execute(preparedStatement);
  //iterate over res, and create list of Data.
  return list;
 }
}

这是我在此说明的一个非常基本的功能。

我已经部署了这个 tomcat 服务器。我听说 Tomcat 有一个线程池,大小为 200(默认情况下)。现在我的问题是,线程池在这里究竟是如何工作的。

假设我有两个请求同时进入。这意味着线程池中的 2 个线程将开始工作。这是否意味着两个线程都将具有我的类服务的实例?因为下面是我对线程和并发的理解。

public class myThread extends Thread(){
    public void run(){
    //do whatever you wan to do here;
    }
}

在上面,当我在我的线程上调用 start 时,它将执行 run() 方法中的代码,并且它在那里创建的所有对象都属于它。

现在,回到 Tomcat,是否在某处编写了 run() 方法来实例化 Services 类,这就是线程池处理 200 个并发请求的方式。 (显然,我知道它们需要 200 个内核才能同时执行,所以请忽略它)。

因为否则,如果tomcat没有200个不同的线程具有相同的执行路径(即我的Services类),那么它将如何处理这200个并发请求。

谢谢

【问题讨论】:

    标签: java multithreading tomcat concurrency threadpool


    【解决方案1】:

    Tomcat 的线程池的工作方式或多或少类似于您从ExecutorService 获得的内容(请参阅Executors)。

    YMMV。 Tomcat 监听请求。当它收到一个请求时,它将这个请求放入一个队列中。并行地,它维护 X 个线程,这些线程将不断尝试从该队列中取出。他们将准备 ServletRequestServletResponse 对象,以及要调用的 FilterChain 和适当的 Servlet

    在伪代码中,这看起来像

    public void run() {
        while (true) {
            socket = queue.take();
            ServletRequest request = getRequest(socket.getInputStream());
            ServletResponse response = generateResponse(socket.getOutputStream());
            Servlet servletInstance = determineServletInstance(request);
            FilterChain chain = determineFilterChainWithServlet(request, servletInstance);
            chain.doFilter(request,response); // down the line invokes the servlet#service method
            // do some cleanup, close streams, etc.
        }
    }
    

    确定适当的 ServletFilter 实例取决于请求中的 URL 路径和您配置的 url 映射。 Tomcat(以及每个 Servlet 容器)只会为部署描述符中声明的每个 &lt;servlet&gt;&lt;filter&gt; 声明管理一个 ServletFilter 实例。

    因此,每个线程都可能在同一个Servlet 实例上执行service(..) 方法。

    这就是 Servlet 规范和 Servlet API 以及 Tomcat 所保证的。


    至于您的 Restful 网络服务,read this。它描述了资源通常是如何成为应用程序范围的单例的,类似于由 Servlet 容器管理的 Servlet 实例。也就是说,每个线程都使用同一个实例来处理请求。

    【讨论】:

    • 所以,如果我理解正确的话。线程池中的每个线程(实际上)都将保存我的 Services 类的相同实例。所以,我不需要将我的 DataSource 的实例设为静态(我猜,将其设为静态也无害),但即使我保持它为非静态,我也可以在声明时实例化它并在之后使用它。
    • @Kraken 没错,不过我建议使用适当的控制容器反转来进行数据源的初始化和注入。
    猜你喜欢
    • 2018-07-19
    • 2013-06-01
    • 2015-03-27
    • 2010-12-15
    • 1970-01-01
    • 1970-01-01
    • 2011-11-03
    • 2013-02-08
    • 1970-01-01
    相关资源
    最近更新 更多