[英]Interrupt Thread in java
我有一種情況,我正在使用線程,她調用了一個可以執行多個進程的方法,我需要使用“取消”按鈕來停止線程,而我不能使用:“ while”,以驗證它已被取消,因為它在此過程中沒有循環。
例如:
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
controller = new FirstEtapaController();
execProcess();
return null;
}
};
new Thread(task).start();
通話方式
private void execProcess() {
Thread thread = new Thread(new Runnable() {
public void run() {
getController().execMhetod();
refreshTable();
}
});
thread.start();
thread.join();
};
即,即使“ ExecMethod” 已在運行 ,我也需要停止該過程,這將需要幾分鍾的時間,因此我必須停止該過程, 而不必等待他完成 ,否則其他操作不會繼續。
請記住,此過程將與我的DAO一起進行迭代。
唯一的方法(行為良好的方法)是在生成的線程中添加邏輯點以檢查中斷狀態。 您可以選擇使用內置的Thread.interrupt()
機制,也可以使用某種形式的線程安全變量( AtomicBoolean
?)或某種信號量來添加自己的邏輯。
如果使用Thread.interrupt()
則子進程在遇到某些條件時會拋出InterruptedException,例如Thread.wait()和其他需要同步或使用java.util.concurrent。*類的方法。
無論如何,您都將(應該已經)處理線程中的InterruptedExceptions
,但是也許您需要在子進程中進行常規的“檢查”以尋找中斷狀態(可以使用Thread.isInterrupted()
)。
如果使用ExecutorService而不是原始線程,則會導致很多其他方法/杠桿來控制線程,其中之一是shutdownAll()
,它使用Thread.interrupt()
殺死線程並讓您檢查通過isTerminated()
線程狀態
您的用戶界面不必等待工作線程完成,因此不必為此太擔心。
遺憾的是,由於錯誤的實現,不贊成使用Thread.destroy()和Thread.stop()。 我認為Java線程沒有很好的“信號消除”類型的替代品。 如果這很重要,您將必須重新編碼工作程序以檢查某種中止標志。 否則,只需浪費一點CPU。 (實際上,“您無法取消該保存-我已經完成了!”)
一個任務是否可以取消實際上取決於它的實現。 通常,它間歇性地檢查標志是否應該繼續。
您可以自己實現這樣的標志,以及設置它的方法:
private volatile boolean shouldStop;
public void cancel() {
shouldStop = true;
}
@Override
public void run() {
while (!shouldStop) {
// do work
}
}
但是線程已經帶有一個標志:被中斷的標志。 盡管不必將其用於取消線程,但通常將其用於特定目的。 實際上,標准的ExecutorService
實現將嘗試通過中斷線程來取消它們的線程。
除此之外,當線程被InterruptedException
時,幾種阻塞方法(將線程置於BLOCKED
或WAITING
狀態的方法)將引發InterruptedException
,這時它們再次變為RUNNABLE
。 這是以前帶有布爾標志的方法無法實現的。
因此,使用中斷來取消任務是一種更好的方法。 而且您實際上也不再需要那種cancel()方法:
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// do work
}
}
另外,任何知道您的線程的代碼都知道如何取消它。 包括標准的ExecutorService
實現。
捕獲InterruptedException
時應格外小心,因為這樣做會清除被中斷的標志。 建議總是在捕獲到異常時恢復中斷的標志,因此客戶也知道是時候停止做他們正在做的事情了。
private BlockingQueue<Integer> queue;
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Integer id = queue.take(); // blocking method
// do work
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
要取消線程,只需保留對Thread
對象的引用並在其上調用interrupt()
:
Thread thread = new Thread(new InterruptibleTask());
thread.start();
// some time after :
thread.interrupt();
但是,一種更優雅的方法是通過Future
對象來監視任務(而不是運行任務的特定線程)。 您可以通過在FutureTask
包裝Runnable
或Callable
來實現。
RunnableFuture<Void> task = new FutureTask<>(new InterruptibleTask(), null);
new Thread(task).start();
// some time after :
task.cancel(true); // true indicating interruption may be used to cancel.
Future
是控制任務的關鍵。 它允許您等待其完成,並有選擇地接收任務計算出的值:
try {
String value = future.get(); // return value is generically typed String is just as example.
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // since future.get() blocks
} catch (ExecutionException e) {
logger.log(Level.SEVERE, "Exception on worker thread", e.getCause()); // the ExecutionException's cause is the Exception that occurred in the Task
}
如果您有多個任務(甚至只有一個),那么值得使用ExecutorService:
ExecutorService pool = Executors.newCachedThreadPool();
Future<?> submit = pool.submit(new InterruptibleTask());
pool.shutdownNow(); // depending on ExecutorService implementation this will cancel all tasks for you, the ones Executors returns do.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.