我試圖在執行 10 秒后停止一個長時間運行的方法,到目前為止我遵循了 baeldung 上的計時器指令。
https://www.baeldung.com/java-stop-execution-after-certain-time#1-using-a-timer
當該方法是對執行緒 sleep 的簡單呼叫時,它可以作業,但是當我使用子方法呼叫我的函式時,它不會停止。
我的實作是這樣的:
class TimeOutTask extends TimerTask {
private Thread t;
private Timer timer;
TimeOutTask(Thread t, Timer timer){
this.t = t;
this.timer = timer;
}
public void run() {
if (t != null && t.isAlive()) {
t.interrupt();
timer.cancel();
}
}
}
class Execution implements Runnable {
private String carpeta;
private Experiment exp;
public Execution(String carpeta, Experiment exp) {
this.carpeta = carpeta;
this.exp = exp;
}
@Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
exp.executeExperiment(carpeta);
}
} catch (InterruptedException e) {
System.out.println("Fin de ejecución por tiempo");
}
}
}
我呼叫這個執行的方式是通過 executeTimedExperiment 方法
public Experiment() {
this.cases = new ArrayList<>();
}
private void executeTimedExperiment(String carpeta){
Thread t = new Thread(new Execution(carpeta,this));
Timer timer = new Timer();
timer.schedule(new TimeOutTask(t, timer), 10000);
t.start();
}
private void executeExperiment(String carpeta) throws InterruptedException {
String[] files = getFiles(carpeta);
Arrays.sort(files);
for (String file : files) {
executeCase(carpeta, file);
}
}
private boolean executeCase(String carpeta, String file) {
Graph g = readDataToGraph(carpeta "/" file);
Solution s = new ExactSolutionGenerator().ExactSolution(g);
addNewCase(file, s);
}
executeExperiment 方法是長時間運行的,我用 InterruptedException 標記了它,但編譯器告訴我從不拋出例外。
現在當我執行它時會發生什么,它可以正常運行而不會停止。
我不確定是否需要將 InterruptedException 添加到子方法或其他東西中,但如果可能的話,我不想觸及子方法。
提前致謝。
uj5u.com熱心網友回復:
您需要做的不僅僅是添加throws InterruptedException到所有這些“子方法”(以及您自己的方法)。必須更改每個方法的主體以正確回應中斷。
無法任意停止運行代碼。中斷是合作的——它們只有在被中斷的執行緒關注它們時才有意義。
您的run()方法正確地做到了這一點:通過將整個回圈放在 try/catch 中,任何 InterruptedException 都會導致回圈終止,因此執行緒將終止。
但是它呼叫的方法必須做同樣的事情。您的run方法呼叫executeExperiment,它執行以下操作:
String[] files = getFiles(carpeta);
我不知道該方法需要多長時間,但如果它需要花費大量時間(超過幾分之一秒),則它需要能夠在檔案讀取程序中拋出 InterruptedException。
executeExperiment 還呼叫executeCase,它呼叫“子方法”readDataToGraph、ExactSolution 和 addNewCase。如上所述,每個需要超過一秒的方法都需要通過拋出 InterruptedException 來回應中斷。所以,恐怕你需要修改它們。
一個例子是:
private Graph readDataToGraph(String filename)
throws InterruptedException {
Graph graph = new Graph();
try (BufferedReader reader = Files.newBufferedReader(Path.of(filename))) {
String line;
while ((line = reader.readLine()) != null) {
graph.addData(convertDataToGraphEntry(line));
if (Thread.interrupted()) {
throw new InterruptedException();
}
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
uj5u.com熱心網友回復:
編譯器告訴你例外永遠不會拋出是因為你的executeExperiment方法是不可中斷的(不像一些阻塞方法,例如Object#wait),所以thread.interrupt不會使執行此方法的執行緒接收到InterruptedException。
也許你每次迭代files你的executeExperiment方法都需要檢查當前執行緒是否被中斷,如果是,則拋出一個InterruptedException。(但這可能仍然不準確,因為該executeCase方法可能會執行很長時間。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/391208.html
