我有一种情况,我正在使用一个Thread,她调用一个会执行多个进程的方法,我需要使用一个“取消”按钮,你必须在其中停止该线程,我不能使用:“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进行迭代。
答案 0 :(得分:2)
唯一的方法(表现良好的方式)是在生成的线程中添加逻辑点以检查中断状态。您可以选择使用内置的Thread.interrupt()
机制,或者使用某种形式的线程安全变量(AtomicBoolean
?)或某种形式的信号量来添加自己的逻辑。
如果使用Thread.interrupt()
,则子进程在遇到某些条件时会抛出InterruptedException,如Thread.wait()和其他需要同步的方法或使用java.util.concurrent。*类。
无论如何,您将需要(应该已经)处理线程中的InterruptedExceptions
,但是您可能需要在子进程中定期“检查”以查找中断状态(可以使用{ {1}})
答案 1 :(得分:1)
如果您使用ExecutorService而不是原始线程,则最终会有许多其他方法/杠杆来控制您的线程,其中一个是shutdownAll()
,它使用Thread.interrupt()
杀死你的线程并让你通过isTerminated()
答案 2 :(得分:0)
您的用户界面无需等待工作线程完成,因此请不要过于担心。
唉,由于实现不好,不推荐使用Thread.destroy()和Thread.stop()。我不认为有一个好的&#34; sig-kill&#34; Java线程的替代类型。如果重要的话,你将不得不重新编码工人以检查某种中止标志。否则,只是让它浪费一点CPU。 (&#34;你不能取消保存 - 我已经完成了它!&#34;,实际上)
答案 3 :(得分:0)
是否可以取消任务实际上取决于其实施。通常它会间歇性地检查标志是否应该继续。
您可以自己实现这样的标志,以及设置它的方法:
private volatile boolean shouldStop;
public void cancel() {
shouldStop = true;
}
@Override
public void run() {
while (!shouldStop) {
// do work
}
}
但线程已经带有一个标志:中断的标志。虽然它不一定用于取消线程,但通常将其用于此目的。实际上,标准ExecutorService
实现将尝试通过中断它们来取消它们的线程。
除了几个阻塞方法(将线程置于BLOCKED
或WAITING
状态的方法)将在线程中断时抛出InterruptedException
,此时它们变为{{ 1}}再次。这是以前使用布尔标志的方法无法实现的。
因此,使用中断以允许取消任务是更好的方法。而且你不再需要那个cancel()方法:
RUNNABLE
作为奖励,任何了解您的线程的代码都知道如何取消它。包括标准@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
或Runnable
包裹在Callable
中来完成此操作。
FutureTask
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
如果您有多个任务(甚至只有一个),则值得使用ExecutorService:
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
}