简短问题:在Tomcat 6应用程序中-如何运行(单独的)线程池?
什么是运行线程池的最佳解决方案?
长问题:
我这里有一个简单的需求。
轮询数据库以获取一些数据,同时允许Web客户端等待答案(长轮询连接)。
当该数据在数据库中可用时,我将向相关客户端发送回复。
这样说,我目前不希望进入任何框架(也许是quartz scheduler
?)。
因此,正如我得出的结论,我需要一个线程池来在后台完成这项工作。
所以,如果我要使用Thread
(实际上是Runnable
),那么哪个类可以组织所有内容? 是否有某种ThreadPool
解决方案?有什么建议吗?
最佳答案
回答您的简短问题:
在JVM中,线程池在java.util.concurrent.ExecutorService
接口之后抽象。该接口有不同的实现,但是在大多数情况下,该接口的方法就足够了。
要创建特定的线程池,请看一看java.util.concurrent.Executors
类:
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html
其中包含用于创建ExecutorService
接口的不同实现的静态工厂方法。您可能对newFixedThreadPool(int threadsNumber)
和newCachedThreadPool
方法感兴趣。
有关JVM中Executors
的更多常规信息,您可能需要阅读以下Oracle教程:http://docs.oracle.com/javase/tutorial/essential/concurrency/executors.html
因此,要在Tomcat下使用线程池(ExecutorService
),您应该执行以下操作:
.1。如果尚未完成,请在web.xml
接口的javax.servlet.ServletContextListener
实例中创建并注册(这将充当您的Web应用程序的入口点)。
.2。在contextInitialized(ServletContextEvent)
方法中,您创建ExecutorService
(线程池)的实例并将其存储在ServletContext
属性映射中,以便可以从您的Web应用程序中的任何位置访问它,例如:
// following method is invoked one time, when you web application starts (is deployed)
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
// ...
final int numberOfThreads = ...;
final ExecutorService threadPool = Executors.newFixedThreadPool(numberOfThreads); // starts thread pool
final ServletContext servletContext = servletContextEvent.getServletContext();
servletContext.setAttribute("threadPoolAlias", threadPool);
// ...
}
// following method is invoked one time when your web application stops (is undeployed)
public void contextDestroyed(ServletContextEvent servletContextEvent) {
// following code is just to free resources occupied by thread pool when web application is undeployed
final ExecutorService threadPool = (ExecutorService) servletContextEvent.getServletContext().getAttribute("threadPoolAlias");
threadPool.shutdown();
}
.3。在
Servlet.service
方法中的某个地方或您的Webapp中的任何地方(您应该几乎可以从Webapp的任何地方获得对ServletContext
的引用):Callable<ResultOfMyTask> callable = new Callable<ResultOfMyTask>() {
public ResultOfMyTask call() {
// here goes your task code which is to be invoked by thread pool
}
};
final ServletContext servletContext = ...;
final ExecutorService threadPool = (ExecutorService) servletContext.getAttribute("threadPoolAlias");
final Future<ResultOfMyTask> myTask = threadPool.submit(callable);;
您应该存储对myTask的引用,并可以从其他线程中查询它,以了解它是否已完成以及结果如何。
希望这可以帮助...