5

私が持っているコードは Callable インスタンスを作成し、 ExecutorService を使用して新しいスレッドが作成されています。スレッドの実行が完了していない場合、一定時間後にこのスレッドを強制終了したいと思います。jdk のドキュメントを読んだ後、Future.cancel() メソッドを使用してスレッドの実行を停止できることに気付きましたが、残念ながら機能していません。もちろん、 future.get() メソッドは、規定の時間 (私の場合は 2 秒) 後にスレッドに割り込みを送信しており、スレッドでさえこの割り込みを受信して​​いますが、この割り込みは、スレッドが実行を終了した後にのみ発生します。完全に。しかし、2秒後にスレッドを殺したいです。

これを達成する方法を教えてください。

テストクラス コード:

====================================

public class TestExecService {

      public static void main(String[] args) {

          //checkFixedThreadPool();
          checkCallablePool();

          }

      private static void checkCallablePool()
      {
          PrintCallableTask task1 = new PrintCallableTask("thread1");

          ExecutorService threadExecutor = Executors.newFixedThreadPool(1);
          Future<String> future = threadExecutor.submit(task1);

          try {
                System.out.println("Started..");
                System.out.println("Return VAL from thread ===>>>>>" + future.get(2, TimeUnit.SECONDS));
                System.out.println("Finished!");
            }
          catch (InterruptedException e) 
          {
            System.out.println("Thread got Interrupted Exception ==============================>>>>>>>>>>>>>>>>>>>>>>>>>");
            //e.printStackTrace();
          }
          catch (ExecutionException e) 
          {
            System.out.println("Thread got Execution Exception ==============================>>>>>>>>>>>>>>>>>>>>>>>>>");
          }
          catch (TimeoutException e)
          {
            System.out.println("Thread got TimedOut Exception ==============================>>>>>>>>>>>>>>>>>>>>>>>>>");
            future.cancel(true);
          }

          threadExecutor.shutdownNow();

      }
}

呼び出し可能なクラス コード:

===================================================================
package com.test;

import java.util.concurrent.Callable;

public class PrintCallableTask implements Callable<String> {

      private int sleepTime;
      private String threadName;

    public PrintCallableTask(String name)
    {
        threadName = name;
        sleepTime = 100000;     
    }

    @Override
    public String call() throws Exception {

        try {
              System.out.printf("%s going to sleep for %d milliseconds.\n", threadName, sleepTime);
              int i = 0;

              while (i < 100000)
              {
                  System.out.println(i++);
              }


              Thread.sleep(sleepTime); // put thread to sleep
              System.out.printf("%s is in middle of execution \n", threadName);

            } catch (InterruptedException exception) {
              exception.printStackTrace();
            }


            System.out.printf("%s done sleeping\n", threadName);

            return "success";
    }

}
4

2 に答える 2

9

あなたのコードはすべてを正しく行います。唯一の問題は、ループをチェックThread.isInterruptedインしていないことです。whileスレッドがメッセージを取得する唯一の方法は、Thread.sleepすぐにスローするブロッキング呼び出しに到達することInterruptedExceptionです。ループが長い場合は、時間がかかることがあります。そのため、コードが少し応答しなくなります。

たとえば、10,000回の反復ごとに中断ステータスを確認します。

while (i < 100000) {

    if (i % 10000 == 0 && Thread.currentThread().isInterrupted())
        return "fail";

    System.out.println(i++);
}

InterruptedException長いブロッキングメソッド用です。Thread.isInterrupted他のすべてのためです。

于 2012-11-29T23:17:51.563 に答える
4

cancel()interrupt()すでに実行中のスレッドを呼び出すだけです。

http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

割り込みは、スレッドが実行していることを停止し、他のことを実行する必要があることをスレッドに示します。スレッドが割り込みにどのように応答するかを正確に決定するのはプログラマー次第ですが、スレッドが終了することは非常に一般的です。

中断されたスレッドはInterruptedExceptionのみをスローします

スレッドが長時間待機中、スリープ中、または一時停止していて、別のスレッドがThreadクラスのinterrupt()メソッドを使用してスレッドを中断した場合。

したがって、スレッドの実行時にジョブコードを明示的に作成して、中断の可能性を認識させる必要があります。

私がそうでない場合、誰がJavaスレッドinterrupt()メソッドを呼び出しているのか?も参照してください。。

「 Java8の完了可能な将来をキャンセルする方法」も参照してください。JavaFuturesはJava8によってのみ成熟したためです。

于 2012-11-29T13:36:21.217 に答える