本当にできません...それを行う唯一の方法は、thread.stopを使用するか、「協調的」メソッドに同意することです(たとえば、Thread.isInterruptedをときどきチェックするか、InterruptedExceptionをスローするメソッド(たとえば、Thread)を呼び出すことです。 sleep())、またはどういうわけか別のJVMでメソッドを完全に呼び出します。
特定の種類のテストでは、stop()を呼び出しても問題ありませんが、テストスイートの状態が損なわれる可能性があるため、相互作用の影響を回避する場合は、stop()を呼び出すたびにJVMを再起動する必要があります。
協調的アプローチを実装する方法の適切な説明については、非推奨のThreadメソッドに関するSunのFAQを確認してください。
実生活でのこのアプローチの例として、 EclipseRCPのJobAPIの「IProgressMonitor」オブジェクトを使用すると、一部の管理サービスがサブプロセスに(「cancel」メソッドを介して)停止するように通知できます。もちろん、それは実際にisCancelledメソッドを定期的にチェックするメソッドに依存していますが、これはしばしば失敗します。
ハイブリッドアプローチは、スレッドに割り込みを適切に要求し、数秒後に停止を要求することです。繰り返しになりますが、本番コードではstopを使用しないでください。ただし、この場合は特に問題ない可能性があります。すぐにJVMを終了した場合。
このアプローチをテストするために、実行可能なものを取得して実行しようとする単純なハーネスを作成しました。コメント/編集してください。
public void testStop(Runnable r) {
Thread t = new Thread(r);
t.start();
try {
t.join(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (!t.isAlive()) {
System.err.println("Finished on time.");
return;
}
try {
t.interrupt();
t.join(2000);
if (!t.isAlive()) {
System.err.println("cooperative stop");
return;
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.err.println("non-cooperative stop");
StackTraceElement[] trace = Thread.getAllStackTraces().get(t);
if (null != trace) {
Throwable temp = new Throwable();
temp.setStackTrace(trace);
temp.printStackTrace();
}
t.stop();
System.err.println("stopped non-cooperative thread");
}
それをテストするために、2つの競合する無限ループを作成しました。1つは協調ループで、もう1つはスレッドの中断されたビットをチェックしません。
public void cooperative() {
try {
for (;;) {
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.err.println("cooperative() interrupted");
} finally {
System.err.println("cooperative() finally");
}
}
public void noncooperative() {
try {
for (;;) {
Thread.yield();
}
} finally {
System.err.println("noncooperative() finally");
}
}
最後に、テスト(JUnit 4)を作成して、それらを実行しました。
@Test
public void testStopCooperative() {
testStop(new Runnable() {
@Override
public void run() {
cooperative();
}
});
}
@Test
public void testStopNoncooperative() {
testStop(new Runnable() {
@Override
public void run() {
noncooperative();
}
});
}
私はこれまでThread.stop()を使用したことがなかったので、その操作に気づいていませんでした。これは、ターゲットスレッドが現在実行されている場所からThreadDeathオブジェクトをスローすることで機能します。これはエラーを拡張します。したがって、常に正常に機能するとは限りませんが、通常は、かなり妥当なプログラム状態の単純なプログラムが残ります。たとえば、finallyブロックが呼び出されます。本当のジャークになりたいのなら、とにかくThreadDeath(またはError)をキャッチして、実行を続けることができます!
他に何もないとしても、これは本当にIProgressMonitorアプローチに従ったコードをもっと望んでいます-時間がかかる可能性のあるメソッドに別のパラメーターを追加し、メソッドの実装者に、ユーザーがシステムに与えることを望んでいるかどうかを確認するためにモニターオブジェクトを時々ポーリングするように促します上。将来的には、特にインタラクティブな方法で、このパターンに従うようにします。もちろん、どの方法がこのように使用されるかを事前に知っている必要はありませんが、それがプロファイラーの目的だと思います。
「別のJVMを完全に開始する」メソッドについては、さらに作業が必要になります。誰かが委任クラスローダーを作成したかどうか、または1つがJVMに含まれているかどうかはわかりませんが、このアプローチにはそれが必要です。