入力セットに対して2つの計算を実行するJavaメソッドがあります。推定された答えと正確な答えです。見積もりは常に安価で信頼できる時間で計算できます。正確な答えは、許容できる時間内に計算できる場合とそうでない場合があります(事前にわかっていない...試してみる必要があります)。
私が設定したいのは、正確な答えに時間がかかりすぎる場合(固定タイムアウト)、代わりに事前に計算された見積もりが使用されるフレームワークです。これにはスレッドを使うと思いました。主な問題は、正確な答えを計算するためのコードが外部ライブラリに依存しているため、割り込みサポートを「注入」できないことです。
この問題のスタンドアロンのテストケースがここにあり、私の問題を示しています。
package test;
import java.util.Random;
public class InterruptableProcess {
public static final int TIMEOUT = 1000;
public static void main(String[] args){
for(int i=0; i<10; i++){
getAnswer();
}
}
public static double getAnswer(){
long b4 = System.currentTimeMillis();
// have an estimate pre-computed
double estimate = Math.random();
//try to get accurate answer
//can take a long time
//if longer than TIMEOUT, use estimate instead
AccurateAnswerThread t = new AccurateAnswerThread();
t.start();
try{
t.join(TIMEOUT);
} catch(InterruptedException ie){
;
}
if(!t.isFinished()){
System.err.println("Returning estimate: "+estimate+" in "+(System.currentTimeMillis()-b4)+" ms");
return estimate;
} else{
System.err.println("Returning accurate answer: "+t.getAccurateAnswer()+" in "+(System.currentTimeMillis()-b4)+" ms");
return t.getAccurateAnswer();
}
}
public static class AccurateAnswerThread extends Thread{
private boolean finished = false;
private double answer = -1;
public void run(){
//call to external, non-modifiable code
answer = accurateAnswer();
finished = true;
}
public boolean isFinished(){
return finished;
}
public double getAccurateAnswer(){
return answer;
}
// not modifiable, emulate an expensive call
// in practice, from an external library
private double accurateAnswer(){
Random r = new Random();
long b4 = System.currentTimeMillis();
long wait = r.nextInt(TIMEOUT*2);
//don't want to use .wait() since
//external code doesn't support interruption
while(b4+wait>System.currentTimeMillis()){
;
}
return Math.random();
}
}
}
これは正常に出力されます...
Returning estimate: 0.21007465651836377 in 1002 ms
Returning estimate: 0.5303547292361411 in 1001 ms
Returning accurate answer: 0.008838428149438915 in 355 ms
Returning estimate: 0.7981717302567681 in 1001 ms
Returning estimate: 0.9207406241557682 in 1000 ms
Returning accurate answer: 0.0893839926072787 in 175 ms
Returning estimate: 0.7310211480220586 in 1000 ms
Returning accurate answer: 0.7296754467596422 in 530 ms
Returning estimate: 0.5880164300851529 in 1000 ms
Returning estimate: 0.38605296260291233 in 1000 ms
ただし、分析を実行するための非常に大きな入力セット(数十億アイテムのオーダー)があり、終了しないスレッドをクリーンアップする方法がわかりません(バックグラウンド)。
スレッドを破棄するさまざまな方法が、正当な理由で非推奨になっていることを私は知っています。また、スレッドを停止する一般的な方法は、割り込みを使用することであることも知っています。run()
ただし、この場合、メソッドが外部ライブラリに1回の呼び出しを渡すため、割り込みを使用できることがわかりません。
この場合、どうすればスレッドを強制終了/クリーンアップできますか?