不包含 while 语句的停止线程

  • 本文关键字:线程 语句 包含 while java
  • 更新时间 :
  • 英文 :


所有答案都是关于如何停止某个线程的循环,但是如果我没有循环,但我仍然想在线程执行/处理所有行之前停止它怎么办?

例如,我有一个线程,它通常运行 7-10 秒,然后死亡(终止):

mThread = new Thread(new Runnable() {
@Override
public void run() {
// some code here 
// some here  
// some here
// some here          
// some here
// all lines takes about 7-10 seconds
}
});

如果我启动了一个线程,并且在 2 或 3 秒后我需要停止它,那么如何做到这一点并且不要等待 10 秒?

如果你的线程没有被阻塞,并且实际上正在处理东西,那么中断它可能无济于事。 您可以对线程进行编码以检查当前线程上的中断标志,然后在看到已设置该标志时停止。

这是检查当前线程是否已中断的方法。

Thread.currentThread().isInterrupted();

所以你必须像这样对你的线程进行编码......

mThread = new Thread(new Runnable() {
@Override
public void run() {
// some code here 
if (Thread.currentThread().isInterrupted()) return;
// some here  
if (Thread.currentThread().isInterrupted()) return;
// some here
if (Thread.currentThread().isInterrupted()) return;
// some here          
if (Thread.currentThread().isInterrupted()) return;
// some here
// all lines takes about 7-10 seconds    
}
});

然后你可以继续中断mThread,它会产生影响。 尽管它仍将继续处理当前some here步骤。

解释

首选方法是在线程中实现停止机制。您也可以尝试观察interrupt标志。您可以使用Thread#interrupt方法从外部中断,线程可以使用Thread#isInterruptedThread#interrupted检查标志(请参阅 Thread 的文档)。

如果没有线程本身实际实现逻辑,就无法强制外部线程停止。有Thread#stop方法,但它已被弃用,永远不应该使用。从其文档中:

已弃用。这种方法本质上是不安全的。使用Thread.stop停止线程会导致它解锁它已锁定的所有监视器(这是未经检查的ThreadDeath异常向上传播堆栈的自然结果)。如果以前受这些监视器保护的任何对象处于不一致状态,则损坏的对象对其他线程可见,这可能会导致任意行为。stop 的许多用法应该替换为代码,这些代码只是修改一些变量以指示目标线程应该停止运行。目标线程应定期检查此变量,如果变量指示要停止运行,则按顺序从其 run 方法返回。如果目标线程等待很长时间(例如,在条件变量上),则应使用 interrupt 方法来中断等待。有关详细信息,请参阅为什么 Thread.stop、Thread.suspend 和 Thread.resume 已弃用?。


溶液

您可以像这样修改线程:

public class MyThread implements Runnable {
private volatile boolean mShouldStop = false;
public void shutdown() {
mShouldStop = true;
}
@Override
public void run() {
// First line ...
if (mShouldStop) return;
// Second line ...
if (mShouldStop) return;
// Third line ...
if (mShouldStop) return;
}
}

因此,您需要定期检查该标志,然后手动中止。

通常这样的线程有某种while (true)循环。在这种情况下,它变得更容易,您可以执行以下操作:

@Override
public void run() {
while (!mShouldStop) {
// Do something ...
}
}

根据您的应用程序,您可以将中断标志解释为线程关闭的信号。那么你的代码可能看起来像

@Override
public void run() {
while (!Thread.interrupted()) {
// Do something ...
}
}

注意

需要volatilemShouldStop,以确保它针对Thread正确更新。请参阅 Oracle 的 Atomic Access 教程。

你用mThread.interrupt()打断线程。但是,要使其正常工作,您的线程需要检查中断状态(通过睡眠)。看看这个线程。

有关更多详细信息,请参阅此线程。

您需要检查线程中的中断状态。 像这样的东西

import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
public class ThreadInterruptor {

private static class Worker implements Runnable {
@Override
public void run() {
while (true) {
IntStream.range(0, Short.MAX_VALUE).forEach(i ->noop());
if (Thread.currentThread().isInterrupted()) {
System.out.println("i got interrupted");
break;
}
}
}
private void noop(){}
}

public static void main(String[] args) throws Exception{
Thread thread = new Thread(new Worker());
thread.start();
TimeUnit.SECONDS.sleep(5);
thread.interrupt();
}
}

最新更新