1

TimeoutTask特定のタイムアウト後に終了する を実装しようとしています。ここに私が持っているものがあります:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class TimeoutTask {

    private Long timeout;
    private TimeUnit unit;

    public TimeoutTask(Long timeout, TimeUnit unit) {
        this.timeout = timeout;
        this.unit = unit;
    }

    public <T> T execute(Callable<T> callable) {
        Objects.requireNonNull(timeout, "Timeout");
        Objects.requireNonNull(unit, "Time Unit");
        Objects.requireNonNull(callable, "Callable");

        ExecutorService service = 
                Executors.newFixedThreadPool(1);
        FutureTask<T> task = new FutureTask<T>(callable);
        service.execute(task);

        try {
            return task.get(timeout, unit);
        } catch (InterruptedException | ExecutionException | TimeoutException cause) {
            if(cause instanceof TimeoutException) {
                System.out.println("\nTimeout occured.");
                task.cancel(true);
            }
        } finally {
            System.out.println("Finally called.");
            service.shutdownNow();
        }

        return null;
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
        Callable<String> callable = () -> {         
            System.out.print("Enter something: ");
            BufferedReader consoleReader = 
                    new BufferedReader(new InputStreamReader(System.in));
            String str = consoleReader.readLine();
            return str;
        };

        TimeoutTask timeoutTask = new TimeoutTask(Long.valueOf(10), TimeUnit.SECONDS);
        timeoutTask.execute(callable);  
    }
}

入力がないとタイムアウトのメッセージが表示されます。ただし、プロセスは終了しません。以下は、Eclipse のコンソールのスクリーンショットです。強調表示された部分を参照してください。

ここに画像の説明を入力

入力を行うと、プロセスはすぐに終了しました。catch ブロックから呼び出しておりFutureTask#cancel、finally ブロックから呼び出しを行ってサービスをシャットダウンするように要求していますExecutorService#shoutDownNow。最終的に呼び出されたことが印刷されていることがわかります。

  • タイムアウトの場合、実行中のプロセスを停止するにはどうすればよいですか?
  • これを達成するためのより良いアプローチはありますか?

Java 8を使用しています。

参照:

アップデート

Marko Topolnikの回答では、原因は中断されない Java IO にあると述べています。だから私は次のように変更しCallableます:

Callable<Long> callable = () -> {           
    long i = 0;
    for(; i <Long.MAX_VALUE;i++){

    }
    return i;
};

この場合、同じことが起こりました。

注:Callableは単なるサンプルです。

4

2 に答える 2