専用スレッドを持つ長いタスクがあります。たとえば、次のようにします。
public static class WorkerThread extends Thread{
@Override public void run () {
for (int i = 1; i<=10; i++) {
System.out.println("worker thread progress: " + i + "/10");
try{Thread.sleep(1000);} catch (InterruptedException ignore) {}
}
System.out.println("the worker thread HAS FINISHED!");
}
}
このタスク中に、ユーザーが長いタスクをキャンセルするためにコマンドラインを聞きたいです。System.in の特性により、コードは次のようになります (つまり、割り込み可能なコンソール読み取りが必要な場合は、ポーリングを使用する必要があります)。
public static class InputThread extends Thread {
@Override public void run() {
try{
StringBuilder sb = new StringBuilder();
do {
while (System.in.available()==0) { Thread.sleep(200); }
sb.append((char)System.in.read());
} while (!sb.toString().equals("cancel\n"));
System.out.println("the user-input thread HAS FINISHED!");
} catch (IOException ignored) {} catch (InterruptedException ie) {}
}
}
では、2 つのスレッドを使用してみましょう。ケースは次のとおりです。
- WorkerThread は InputThread より前に終了します。この場合、ユーザーがスレッドをキャンセルする可能性がなくなるため、(適切に) InputThread を中断する必要があります。
- InputThread は WorkerThread より前に終了します。ユーザーが「キャンセル」コマンドを入力したため、WorkerThread を (適切に) 中断する必要があります
優雅にとは、もちろんコードが中断可能でなければならないことを意味しますが、これは問題のポイントではありません。問題は、2 つのスレッドを開始した後、「最初のスレッドが終了する」のをどのように待つかということです。
public static void main (String [] args) throws InterruptedException {
InputThread it = new InputThread();
it.start();
WorkerThread wt = new WorkerThread();
wt.start();
}