有人可以在这里提出建议吗?我有一种情况,用户将通过Java JSP和servlet以交互方式将数据挖掘请求提交给我的应用程序,该应用程序将动态地计算出关于数据的关联规则等。
由于这样的工作可能需要一段时间,我正在考虑服务器上的某种过程在后台运行这样的请求,因此它不会“锁定”会话并可能使用大量的服务器内存损害了系统。
由于系统由一系列通过MySQL数据库在Tomcat容器中运行的Java JSP和servlet组成,任何人都可以提出建议吗?
由于
摩根先生答案 0 :(得分:48)
你应该做一些事情,将线程标记为一个守护程序线程,因此它至少不会在错误情况下占用tomcat,并且你应该在servlet上下文被破坏时停止执行程序(例如,当你重新部署或停止你的应用程序。为此,请使用ServletContextListener:
public class ExecutorContextListener implements ServletContextListener {
private ExecutorService executor;
public void contextInitialized(ServletContextEvent arg0) {
ServletContext context = arg0.getServletContext();
int nr_executors = 1;
ThreadFactory daemonFactory = new DaemonThreadFactory();
try {
nr_executors = Integer.parseInt(context.getInitParameter("nr-executors"));
} catch (NumberFormatException ignore ) {}
if(nr_executors <= 1) {
executor = Executors.newSingleThreadExecutor(daemonFactory);
} else {
executor = Executors.newFixedThreadPool(nr_executors,daemonFactory);
}
context.setAttribute("MY_EXECUTOR", executor);
}
public void contextDestroyed(ServletContextEvent arg0) {
ServletContext context = arg0.getServletContext();
executor.shutdownNow(); // or process/wait until all pending jobs are done
}
}
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
/**
* Hands out threads from the wrapped threadfactory with setDeamon(true), so the
* threads won't keep the JVM alive when it should otherwise exit.
*/
public class DaemonThreadFactory implements ThreadFactory {
private final ThreadFactory factory;
/**
* Construct a ThreadFactory with setDeamon(true) using
* Executors.defaultThreadFactory()
*/
public DaemonThreadFactory() {
this(Executors.defaultThreadFactory());
}
/**
* Construct a ThreadFactory with setDeamon(true) wrapping the given factory
*
* @param thread
* factory to wrap
*/
public DaemonThreadFactory(ThreadFactory factory) {
if (factory == null)
throw new NullPointerException("factory cannot be null");
this.factory = factory;
}
public Thread newThread(Runnable r) {
final Thread t = factory.newThread(r);
t.setDaemon(true);
return t;
}
}
您必须将上下文侦听器添加到web.xml,您还可以在其中指定要运行后台作业的线程数:
<listener>
<listener-class>com.example.ExecutorContextListener</listener-class>
</listener>
您可以从servlet访问执行程序并向其提交作业:
ExecutorService executor = (ExecutorService )getServletContext().getAttribute("MY_EXECUTOR");
...
executor.submit(myJob);
如果你正在使用Spring,那么所有这些甚至可能都是simpler
答案 1 :(得分:5)
我认为Quartz调度程序应该能够完成你想要做的事情。以下是一些examples from Quartz。使用此方法,您可以启动快速轮询以处理传入请求的cron。我实际上是为我的一个项目做过的。
答案 2 :(得分:3)
轻量级解决方案(与使用像quartz这样的调度程序相反)是将处理放入后台线程并通过ExecutorService运行。
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html
答案 3 :(得分:0)
也许JMS是你真正想要的,但它需要额外的努力才能在Tomcat上使用它,因为它只是Servlet容器。您可以转到像Glassfish或JBoss这样的真实AppServer,或者通过您自己的(在链接下方)向Tomcat添加JMS功能
http://blogs.captechconsulting.com/blog/jairo-vazquez/tomcat-and-jms