2

Runnableを定期的ScheduledExecutorServiceに呼び出す があります(代わりに使用できたはずです)。scheduleWithFixedDelay()scheduleAtFixedRate()

エラーが発生した場合の対処方法を検討中です。簡単に回復できないものである場合(*)、それ以降のすべての呼び出しを停止するオプションが欲しいのですが、これを行う最善の方法がわかりません.

どうやらチェック済みの例外は Runnable からスローできないため、次から選択する方法についてのガイダンスをいただければ幸いです。

scheduledFuture.cancel(false);
...or...
scheduledFuture.cancel(true);
...or...
scheduledExecutorService.shutdown();
...or...
scheduledExecutorService.shutdownNow();
...or...
Throw a custom RuntimeException myself?
...or...
Something else?

(*) 一般的なケースを知りたいのですが、誰かが興味を持っている場合のために、私が現在見ているチェック例外はParserConfigurationExceptionからスローされDocumentBuilderFactory.newDocumentBuilder()ます。これがスローされた場合、それは重大な問題を示しているため、基本的に、毎回エラーを繰り返すのではなく、スケジューリングを完全に停止したいと考えています。

4

2 に答える 2

1

上記の役立​​つコメントのいくつかに基づいて、現在のコードの要点を以下に示します。いくつかの q が残っているため、さらにコメントを歓迎します。

public class ScheduledTask implements Runnable {
    // Configurable values
    private static final int CORE_THREAD_POOL_SIZE = 1;
    private static final int INITIAL_DELAY_MS = 0;
    private static final int INTERVAL_MS = 1000;

    private final ScheduledExecutorService scheduledExecutorService = 
        Executors.newScheduledThreadPool(ScheduledTask.CORE_THREAD_POOL_SIZE);

    private ScheduledFuture<?> scheduledFuture;

    public void run() {
        try {
            try {
                // Do stuff
            } catch RecoverableCheckedException rce { // E.g. SAXException
                // Log and handle appropriately
            }
        } catch UnrecoverableCheckedException uce { // E.g. ParserConfigurationException
            // Not 100% happy with this. It means the caller would need to call
            // getCause() to get the real Exception in this case. But other 
            // RuntimeExceptions wouldn't be wrapped. Could consider catching
            // and wrapping all RuntimeExceptions but I like that even less!
            throw new RuntimeException(uce);
        }
    }

    public boolean isScheduling() {
        return (this.scheduledFuture != null)
               && (!this.scheduledFuture.isDone());
    }

    // May not be needed but provided in case this class is shared.
    public boolean isShutdown() {
        return scheduledExecutorService.isShutdown();
    }

    public void start() {
        // If the Executor Service has already been shutdown, would expect
        // a RejectedExecutionException to be thrown here(?) Not sure what
        // would happen if this method were called when isScheduling() is
        // true?
        this.scheduledFuture = 
            this.scheduledExecutorService.scheduleWithFixedDelay(
                this,
                ScheduledTask.INITIAL_DELAY_MS,
                ScheduledTask.INTERVAL_MS,
                TimeUnit.MILLISECONDS);
    }

    // To be called once at the very end - e.g. on program termination.
    public void shutdown() {
        this.scheduledExecutorService.shutdown();
    }
}
于 2012-12-24T10:54:24.680 に答える
1

おそらく、 FutureとともにCallableを使用できます。これにより、非同期タスク内からチェック済み例外をスローできますが、タスクごとに必要に応じてキャッチして処理できます。

そのアプローチを使用する場合、タスク自体が例外の処理方法を決定できるようにすることが、おそらく最も理にかなっています。この回答を参照してください:

ただし、タスク自体の外で例外を処理する場合は、タスクごとに別のスレッドが必要になると思います。考えられるオプションの 1 つを次に示します。

    ScheduledExecutorService scheduleExecutor;
    scheduleExecutor = = Executors.newScheduledThreadPool(10); // or whatever

    ExecutorService workerExecutor;
    workerExecutor = Executors.newSingleThreadExecutor(); // or whatever

    public void schedule(final long fixedDelay) {

      scheduleExecutor.scheduleWithFixedDelay(new Runnable() {

        @Override
        public void run() {

            Future<Void> future = workerExecutor.submit(new Callable<Void>() {

                @Override
                public Void call() throws Exception {

                    // Do work here. Throw appropiate exception as needed.

                    return null;
                }
            });

            // Now you can catch and handle the exception in whatever
            // way you need to. You can cancel just this task (which is likely
            // redundant by this point), or you can choose to shutdown
            // all other scheduled tasks (which I doubt is what you want).

            try {
                future.get();
            } catch (Exception e) {
                future.cancel(true);
            }

        }
    }, 0, fixedDelay, TimeUnit.MILLISECONDS);

}
于 2012-12-21T17:01:58.890 に答える