Запуск фоновой Java-программы в Tomcat

Кто-нибудь может посоветовать здесь? У меня есть ситуация, когда пользователи будут отправлять запросы интеллектуального анализа данных в интерактивном режиме через Java JSP и сервлет в мое приложение, которое будет динамически разрабатывать правила связывания данных и многое другое.

Поскольку такая работа может занять некоторое время, я думаю о каком-то процессе на сервере для запуска такого запроса в фоновом режиме, чтобы он не блокировал сеанс и, возможно, не использовал огромные объемы памяти сервера в ущерб системы.

Поскольку система состоит из серии Java-JSP и сервлетов, работающих в контейнере Tomcat над базой данных MySQL, кто-нибудь может посоветовать дальнейший путь?

Спасибо

Мистер морган

4 ответа

Используйте ExecutorService.

Однако есть несколько вещей, которые вы должны сделать, пометить поток как поток демона, чтобы он по крайней мере не связывал tomcat в сценариях ошибок, и вы должны остановить исполнителя, когда ваш контекст сервлета разрушен (например, когда вы повторно развертываете или останавливаете свое приложение). Для этого используйте 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>

Вы можете получить доступ к исполнителю из вашего сервлета и отправить ему задания:

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

Если вы используете Spring, все это, вероятно, можно сделать еще проще

Я думаю, что кварцевый планировщик должен быть в состоянии выполнить то, что вы хотите сделать здесь. Вот несколько примеров из кварца. Используя это, вы можете запустить cron, который быстро опрашивает для обработки входящих запросов. Я действительно сделал это для одного из моих проектов.

Облегченное решение (в отличие от использования планировщика, такого как кварц) состояло бы в том, чтобы поместить обработку в фоновый поток и запустить ее через 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

Возможно, JMS - это то, что вы действительно ищете, однако для его использования на Tomcat требуются дополнительные усилия, поскольку это всего лишь контейнер сервлетов. Вы можете перейти на настоящий AppServer, такой как Glassfish или JBoss, или добавить JMS-функциональность в Tomcat самостоятельно (ссылка ниже)

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

Другие вопросы по тегам