7

Java の Future.get() に奇妙な問題があります。常に InterruptedException で返されますが、奇妙なことに、例外の原因が null であるため、誰が私を中断したのかわかりません..

get() を呼び出す前にチェックし、Future が実行しなければならない仕事は既に完了しているため、さらに悪化します。

以下の出力を担当するコードを次に示します。f は Futureであり、 callable は Agent が実際には関連しない HashMap を返します。印刷行が多すぎる場合は申し訳ありませんが、できるだけ多くの情報を提供しようとしています。callable からの call メソッドは、今のところ単純なSystem.out.println("Hola soy agente")もので、後でわかるように出力されます。つまり、callable が例外を引き起こさなかったことを意味します。

コードは次のとおりです。

try
    {
        System.out.println(f.isDone());        //true
        System.out.println(f.isCancelled());   //false
        System.out.println(f.toString());      //FutureTask
        newModdedAgents.putAll(f.get());
    }catch(InterruptedException e)
    {
        System.out.println(f.isDone());        //true
        System.out.println(f.isCancelled());   //false
        System.err.println(e);                 //It is an interruptedException
        System.err.println(e.getCause());     //???? null?
        e.printStackTrace();
    }

そして出力

 Hola soy agente
 true
 false
 java.util.concurrent.FutureTask@1c4c94e5
 true
 false
 java.lang.InterruptedException
 null

java.lang.InterruptedException
at     java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1302)
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:248)
at java.util.concurrent.FutureTask.get(FutureTask.java:111)
at com.pf.simulator.Simulation.simulateStep(Simulation.java:217)
at com.pf.gui.ButtonPanel.doWork(ButtonPanel.java:141)
at com.pf.gui.ButtonPanel$1$1.construct(ButtonPanel.java:198)
at com.pf.gui.SwingWorker$2.run(SwingWorker.java:117)
at java.lang.Thread.run(Thread.java:636)

呼び出し可能オブジェクトをスレッドプールに送信する場所を確認したい場合は、これがそのコードになります

    for(Callable<HashMap<Integer, Agent>> c : agentCallables)
    {
        Future<HashMap<Integer,Agent>> future = pool.submit(c);
        agentFutureSet.add(future);
    }

その後、この Set を次のように反復処理します

    for(Future<HashMap<Integer, Agent>> f : agentFutureSet)
    try
    {
              //Here goes the code at the beginning
4

4 に答える 4

10

呼び出す前にスレッドの割り込みフラグを確認しましたget()か?これは。で行うことができますThread.currentThread().isInterrupted()

詳細については、Future.get()のjavadocを参照して、InterruptedExceptionがスローされる理由を確認してください。

于 2010-11-24T15:37:03.143 に答える
6

InterruptedExceptionからスローされるベア.get()は、現在の実行スレッド ( を呼び出しているスレッド) が を呼び出す前、または でブロックされている間.get()に中断されたことを示します。これは、executor スレッドまたはそのタスクの 1 つが中断されることと同じではありません。誰かまたは何かがあなたの「メイン」スレッド、または少なくともスレッド呼び出しを中断しています。get().get().get()

割り込みはランダムに発生するわけではありません。コードによっては、意図的に割り込みを発生させる必要があります。割り込みはへの呼び出しによってのみ開始できますが、 やThread.interrupt()など、バックグラウンドでこれを呼び出す標準 Java ユーティリティがいくつかFuture.cancel(true)ありExecutorService.shutdownNow()ます。

私の知る限り、中断の原因の「原因チェーン」または「スタックトレース」を外部から追跡する方法はありません。ソースコードを調べて、中断を開始できる場所を特定し、ケースで中断を引き起こしているメソッド呼び出しを推測する必要があります。

于 2010-11-24T16:20:26.397 に答える
1

例外の原因はThrowableです(メソッド呼び出しは例外ではありません)

スレッドは、あなたがそれを引き起こした場合にのみ中断され、ランダムに発生することはありません。

割り込みがどこから来ているのか本当にわからず、それを無視したい場合は、最初にそれをクリアすることができます。電話Thread.interrupted()

于 2010-11-24T15:37:13.783 に答える
0

これは、送信されたCallableを実行しているスレッドが中断されたことを示しています。これは、正当な中断(たとえば、がCallableThread.sleepなどのブロッキング操作を実行し、を介して明示的に中断されThread.interrupt()た場合)であるか、ExecutorService(これを使用していると仮定して)への呼び出しを介してシャットダウンされている可能性がありますshutDownNow()

Callableスレッドプールの作成に使用したコードを実装とともに投稿していただけますか?

于 2010-11-24T15:40:06.830 に答える