web-dev-qa-db-ja.com

TomcatでバックグラウンドJavaプログラムを実行する

誰でもここでアドバイスできますか?私は、ユーザーがJava JSPおよびサーブレットを介してデータのマイニング要求を対話的に私のアプリケーションに送信し、データなどの関連ルールを動的に実行する状況があります。

このようなジョブには時間がかかる場合があるため、セッションを「ロック」せず、おそらく大量のサーバーメモリを使用しないように、バックグラウンドでそのようなリクエストを実行するサーバー上の何らかのプロセスを考えていますシステムの。

システムは一連のJava JSPと、MySQLデータベース上のTomcatコンテナで実行されるサーブレットで構成されているため、誰もが先に進む方法をアドバイスできますか?

ありがとう

モーガン氏

40
mr morgan

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を使用している場合、これはすべて simpler

48
nos

Quartzスケジューラは、ここでやりたいことを達成できるはずです。 Quartzの例 の一部を次に示します。これを使用すると、cronを起動して、迅速にポーリングして着信要求を処理できます。私は実際に私のプロジェクトの1つでそれをしました。

5
limc

(クォーツのようなスケジューラを使用するのではなく)軽量のソリューションは、処理をバックグラウンドスレッドに入れ、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でそれを使用するには余分な労力が必要です。あなたは、GlassfishやJBossのような実際のAppServerに切り替えるか、自分でTomcatにJMS機能を追加することができます(リンクの下)

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

0