在 Tomcat 中运行后台 Java 程序

发布于 2024-10-16 04:13:08 字数 312 浏览 4 评论 0原文

有人可以在这里提供建议吗?我遇到过这样的情况:用户将通过 Java JSP 和 servlet 以交互方式向我的应用程序提交数据挖掘请求,该应用程序将动态地制定数据等的关联规则。

由于这样的工作可能需要一段时间,我正在考虑服务器上的某种进程在后台运行这样的请求,这样它就不会“锁定”会话,并且可能会使用大量的服务器内存,从而造成损害系统的。

由于该系统由一系列 Java JSP 和 servlet 组成,这些 Java JSP 和 servlet 在 MySQL 数据库上的 Tomcat 容器中运行,有人可以建议前进的方向吗?

谢谢

摩根先生

Can anyone advise here? I have a situation where users will submit data mining requests interactively via a Java JSP and servlet to an application of mine which will dynamically work out association rules on data and more.

As such a job may take a while, I'm thinking of some sort of process on the server to run such a request in the background so it dosen't 'lock' the session and possibly use massive amounts of server memory to the detriment of the system.

As the system is made up of a series of Java JSPs and servlets running in a Tomcat container over a MySQL database, can anyone advise a way forward?

Thanks

Mr Morgan

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

帅气称霸 2024-10-23 04:13:08

使用 ExecutorService

不过,您应该做一些事情,将线程标记为守护线程,这样它至少不会在错误情况下占用 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>

您可以从您的 web.xml 访问执行程序 。 servlet 并向其提交作业:

ExecutorService executor = (ExecutorService )getServletContext().getAttribute("MY_EXECUTOR");
...
executor.submit(myJob);

如果您使用 Spring,所有这些甚至都可以更简单

Use an ExecutorService.

There's a few things you should do though, mark the thread as a daemon thread so it atleast won't tie up tomcat in error scenarios, and you should stop the executor when your servlet context is destroyed (e.g. when you redeploy or stop your application. To do this, use a 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;
    }
}

You'll have to add the context listener to your web.xml, where you also can specify the number of threads you'll want to run the background jobs:

  <listener>
    <listener-class>com.example.ExecutorContextListener</listener-class>
  </listener>

You can access the executor from your servlet and submit jobs to it:

ExecutorService executor = (ExecutorService )getServletContext().getAttribute("MY_EXECUTOR");
...
executor.submit(myJob);

If you're using Spring, all this can probably be made even simpler

相思故 2024-10-23 04:13:08

我认为 Quartz 调度程序应该能够完成你在这里想做的事情。以下是一些 Quartz 的示例。使用它,您可以启动一个 cron 来快速轮询以处理传入的请求。我实际上是为我的一个项目这样做的。

I think Quartz scheduler should be able to accomplish what you want to do here. Here are some of the examples from Quartz. Using this, you can start a cron that rapidly polls to process the incoming request(s). I actually did that for one of my projects.

那小子欠揍 2024-10-23 04:13:08

一个轻量级的解决方案(与使用诸如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

A lightweight solution (as opposed to using a scheduler like quartz) would be to put the processing into a background thread and run that through an 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

花伊自在美 2024-10-23 04:13:08

也许 JMS 才是您真正需要的,但是在 Tomcat 上使用它需要额外的努力,因为它只是 Servlet 容器。您可以切换到真正的 AppServer,如 Glassfish 或 JBoss,或者自行将 JMS 功能添加到 Tomcat(下面的链接)

Maybe JMS is what you really looking for however it requires extra effort to use that on Tomcat because it is only Servlet Container. You may eigher switch to real AppServer like Glassfish or JBoss or add JMS functionality to Tomcat by your own (below link)

http://blogs.captechconsulting.com/blog/jairo-vazquez/tomcat-and-jms

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文