0

ThreadPoolExecutor バック タスク実行モジュールがあります。一部のタスクはアプリケーション コードで終了しているように見えますが、ワーカー コードは何らかの理由で try/catch/finally をすべてスキップして次のタスクを取得するだけで、前のタスクで重要なステータス レポート コードが失われています。

この例のように、257832:5 はスレッド 8 によって取得されましたが、このスレッドは最終的に別のタスクを開始するだけです。

2012-07-11 15:53:39,389 INFO [pool-1-thread-6]: タスク (258861:5): 開始しています。
2012-07-11 15:53:39,389 情報 [pool-1-thread-6]: ### を実行しているタスクがアプリ ロジックによってログに記録されました
2012-07-11 15:54:18,186 INFO [pool-1-thread-6]: タスク (258868:5): 開始しています。### 突然別のピックアップ !
2012-07-11 15:54:18,186 情報 [pool-1-thread-6]: ### を実行しているタスクがアプリ ロジックによってログに記録されました
2012-07-11 15:54:18,445 情報 [pool-1-thread-6]: タスク (258868:5): Task.doWork から返されました。
2012-07-11 15:54:18,446 INFO [pool-1-thread-6]: タスク (258868:5): ファイナライズ中。
2012-07-11 15:54:18,487 INFO [pool-1-thread-6]: タスク (258868:5): ステータス結果の通知: 200。
2012-07-11 15:54:18,487 INFO [pool-1-thread-6]: タスク (258868:5): 完了

ThreadPoolExecutor の Runnable は正常に見えます。のように見えます

public void run() {
    log.info(String.format("Task (%s:%s) : Starting.", wfId, taskId));
    try {
        Object result = task.doWork(...); // call the application codes
        log.info(String.format("Task (%s:%s) : returned from Task.doWork.", wfId, taskId));
        status = "DONE";
    } catch (Throwable t) {
        log.error("Error executing task: " + taskId + " - " + className);
    } finally {
        log.info(String.format("Task (%s:%s) : finalizing.", wfId, taskId));
        // notify status to a server
        log.info(String.format("Task (%s:%s) : Finished", wfId, taskId));
    }
}
    // the task framework looks like
    // Use a queue size larger than numThreads, since the ThreadPoolExecutor#getActiveCount() call only returns an approximate count
    this.executor = new ThreadPoolExecutor(numThreads, numThreads, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(numThreads * 2));
    executor.execute(new TaskRunnable(...));

ノート:

  1. 究極の Throwable をキャッチしますが、2 つのタスク間でログに記録される例外はありません
  2. exit() が呼び出されたり、プログラムが再起動したりする兆候はありません
  3. 最初のものはすべてのログ行をスキップしました。これは、アプリ コードへの呼び出しの直後か、catch 内のものか、最終的にブロックされたものかに関係なく、ステータス レポート コードをスキップします。
  4. これは低い確率でランダムに発生します。しかし、実行されるタスクの数が多いため、依然として多くの頭痛の種になります。

これは、スレッド プール エグゼキューターが実行中の実行可能オブジェクトを魔法のように単純に削除するかのように発生します (そうしないと、Throwable としてキャッチされる InterruptedException が必要になります。Java スレッドは、シャットダウン/終了中を除き、非協調的に停止されません)。ブロック。ThreeadPoolExecutor javadoc を確認しましたが、そのようなイベントが発生することはありません。

何が起こったのでしょうか?

4

1 に答える 1

0

finally ブロックからのログ メッセージが表示されない理由として考えられるのは、finally ブロックの実行中に例外がスローされたことです。

  • logその時点で が null の場合、NPE が発生します。(可能性のある原因としてこれを排除できるlogと宣言されている場合。)final

  • wfIdオブジェクトによっては、またはtaskIdオブジェクトのtoString()メソッドで未チェックの例外が発生する可能性があります。

  • Loggerオブジェクトが壊れている可能性があります...


また、何らかの理由で間違ったソース コードを参照している可能性もあります。


さらにもう 1 つの理論的な可能性は、Android プラットフォームThread.destroy()が実際に何かを実行するために実装し、スレッド上で何かがそれを呼び出したことです。この非推奨のメソッドが元の javadoc に従って実装されている場合、finallyブロックが実行されていないことがわかります。これと同等のことを JVM の外部から実行できる場合もあります。しかし、これが起こっているのであれば、すべての賭けはオフです!!

于 2012-07-12T02:43:53.893 に答える