java中的中断线程
我使用一个线程,她调用一个方法来执行多个进程,我需要使用一个“取消”按钮来停止线程,我不能使用“while”来验证它是否被取消,因为它在这个进程中没有循环 例: 也就是说,我需要停止这个过程,即使“ExecMethod”已经运行了,也需要几分钟的时间,所以我必须停止它,不必等待他完成,这样其他人就不会继续了 记住这个过程将使用我的DAO进行迭代。唯一的方法(行为良好的方法)是在生成的线程中添加逻辑点,以检查中断状态。您可以选择使用内置的java中的中断线程,java,Java,我使用一个线程,她调用一个方法来执行多个进程,我需要使用一个“取消”按钮来停止线程,我不能使用“while”来验证它是否被取消,因为它在这个进程中没有循环 例: 也就是说,我需要停止这个过程,即使“ExecMethod”已经运行了,也需要几分钟的时间,所以我必须停止它,不必等待他完成,这样其他人就不会继续了 记住这个过程将使用我的DAO进行迭代。唯一的方法(行为良好的方法)是在生成的线程中添加逻辑点,以检查中断状态。您可以选择使用内置的Thread.interrupt()机制,或者使用某种形式的
Thread.interrupt()
机制,或者使用某种形式的线程安全变量(一个AtomicBoolean
?)或某种信号量添加您自己的逻辑
如果您使用Thread.interrupt()
,那么您的子进程在遇到某些情况时会抛出InterruptedException,例如Thread.wait()和其他需要同步或使用java.util.concurrent.*类的方法
无论如何,您都需要(应该已经)处理线程中的InterruptedExceptions
,但是您可能需要在子进程中进行常规的“检查”,以查找中断状态(可以使用Thread.isInterrupted()
)
如果您使用一个新的线程,而不是一个原始线程,那么您将得到许多额外的方法/杠杆来控制您的线程,其中一个是
shutdownlall()
,它使用Thread.interrupt()
终止您的线程,并允许您通过isTerminated()检查线程状态
您的用户界面不必等待工作线程完成,所以不要太担心这一点
遗憾的是,Thread.destroy()和Thread.stop()由于实现不好而被弃用。我认为没有一个好的“sigkill”类型的Java线程替代品。如果中止标志很重要的话,您将不得不对工作者重新编码以检查某种中止标志。否则,就让它浪费一点CPU。(“你不能取消保存,我已经完成了!”任务是否可以取消实际上取决于它的实现。通常,它会间歇性地检查标志是否应继续 您可以自己实现这样一个标志,以及设置它的方法:
private volatile boolean shouldStop;
public void cancel() {
shouldStop = true;
}
@Override
public void run() {
while (!shouldStop) {
// do work
}
}
但是线程已经带有一个标志:中断标志。虽然它不一定用于取消线程,但通常用于取消线程。事实上,标准的ExecutorService
实现将试图通过中断线程来取消线程
除此之外,当线程被中断时,一些阻塞方法(将线程置于BLOCKED
或WAITING
状态的方法)将抛出InterruptedException
,此时它们再次变为RUNNABLE
。这是以前使用布尔标志的方法无法实现的
因此,使用中断来允许取消任务是一种更好的方法。您也不再需要cancel()方法:
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// do work
}
}
另外,任何了解线程的代码都知道如何取消线程。包括标准ExecutorService
实现
捕获中断异常时应小心,因为这样做会清除中断标志。建议在捕获异常时始终恢复中断标志,这样客户机也知道是时候停止他们正在做的事情了
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();
}
}
}
但更优雅的方法是通过未来
对象跟踪任务(而不是它运行的特定线程)。您可以通过将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.
如果您有多个任务(甚至只有一个),则值得使用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.
ExecutorService-pool=Executors.newCachedThreadPool();
Future submit=pool.submit(new interruptabletask());
pool.shutdownNow();//根据ExecutorService实现,这将取消执行者返回的所有任务。
2件事:按照您现在的方式,方法call()
几乎会立即返回,它不会等到execProcess()
完成。此外,停止线程的最佳方法是使用标志,并在每一步后检查它。线程应该是要退出的线程,外部请求不应该终止线程。搜索[java]线程中断
并没有告诉您想要知道什么?中断只是一些java方法受影响的标志,但不是很多。如果您需要可靠性,那么您需要自己检查状态。您被中断的线程仍然需要检查自身,以查看它是否已被中断(通过抛出InterruptedException的方法之一,或者通过检查thread.isInterrupted()。此操作有效,但仅在下一个进程中有效,如果它已在运行,则不会停止该进程。仅在下一个进程中有效。
Thread thread = new Thread(new InterruptibleTask());
thread.start();
// some time after :
thread.interrupt();
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.
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 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.