1

簡単なバックグラウンド プロセスの計算を実行したいのですが、わかりません。何をしてもブロックされます。

public class WorkThreadManagerContextLoaderListener implements ServletContextListener {
    private Runnable runnable;
    private WorkManager workManager;

    @Override
    public void contextInitialized(ServletContextEvent event) {
        final WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
        workManager = (WorkManager) springContext.getBean("workThreadManager");

        runnable = new WorkThreadManagerStartUp(WorkManager);

        runnable.run();
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        workManager.shutDown();
    }
}

WorkThreadManagerStartUp が存在する理由は、ブロックしたくないので Runnable 型にし、run() が呼び出されると ExecutorService を起動するためです。

public class UnitOfWorkThreadManagerStartUp implements Runnable {
    private WorkManager workManager;

    public UnitOfWorkThreadManagerStartUp(WorkManager workManager) {
        this.workManager = workManager;
    }

    @Override
    public void run() {
        workManager.startUp();
    }
}

public class WorkThreadManager implements WorkManager {
    @Autowired
    private WorkService workService;

    private final int availableProcessors = Runtime.getRuntime().availableProcessors();
    private final ExecutorService executorService = Executors.newFixedThreadPool(4 * availableProcessors);

    @Override
    public void startUp() {
        // this method always blocks...
    }
}

しかし、私のソリューションは期待どおりに機能しません。Tomcat 7.0.30 で実行しています。

私が理解しようとしているのは、startUp() が常にブロックされているために現在完全にオンラインになることができないため、Web アプリのデプロイを停止せずにバックグラウンドでスレッド プールを開始する方法です。このソリューションを簡素化し、必要がなければ WorkThreadManagerStartUp クラスを削除したいと思います。

編集:

スタートアップクラスを変更しました

public class WorkThreadManagerStartUp implements Runnable {
    private WorkManager workManager;

    public WorkThreadManagerStartUp(WorkManager workManager) {
        this.workManager = workManager;
    }

    @Override
    public void run() {
    try {
        while (true) {
                System.out.println("Hello World!");
                Thread.sleep(1000 * 10);
            }
        } catch(InterruptedException e) {
            System.out.println(e.getMessage());
        }
    }
}

これは独自のスレッドで実行されることになっていますが、Hello World! 期待どおりに複数回表示されますが、Web アプリをオンラインにすることはできません。

4

1 に答える 1

1

ソースを見ると、実際に作成されているスレッドはありません。通常、スレッドをフォークするには、次のようなことを行います。

new Thread(new WorkThread(...)).start();

WorkThread.run()これにより、新しいスレッドでメソッドが呼び出されます。を使用している場合ExecutorService(通常、 を使用する「手動」コードよりも推奨されますThread)、次のようにします。

executorService.submit(new WorkThread(...));
...
// when done with the service you have to shut it down
executorService.shutdown();

WorkManagerクラスをリスナークラスに注入する場合はsubmit(...)、マネージャーにメソッドを追加し、リスナーで次のようにします。

workManager.submit(new WorkThread());

これは、WorkThreadManagerStartUpクラスが必要ないことを意味します。ワーカー スレッドまたは作業単位をサービスに送信します。

Springに関しては、WorkManagerクラスを実装InitializingBeanDisposableBeanて、サービス自体を開始および停止できるようにするだけです。別の Bean にそれをさせる理由はありません。WorkThread次に、マネージャーによって管理されているを使用して実行したいクラスにマネージャーを挿入できますExecutorService

于 2012-10-10T14:00:07.240 に答える