Java中的thread.stop()方法是如何工作的?

8
我实际上正在寻找一种更简单的方法来杀死线程,无论线程在哪里运行。但是互联网上大多数解决方案都指向使用布尔标志来控制线程的执行,如果要停止线程,则将布尔变量设置为false。
但是,如果可运行代码块中的任务是一个长时间的线性任务,那该怎么办呢?在这种情况下,创建一个“while”循环以覆盖整个任务块并不容易。
使用Thread.stop确实很诱人,但是警告“已弃用”似乎相当危险。我阅读了这篇文章Why Are Thread.stop, Thread.suspend, Thread.resume and Runtime.runFinalizersOnExit Deprecated? 但我不理解
如果之前受这些监视器保护的任何对象处于不一致状态,则其他线程现在可能会查看这些对象处于不一致状态。这样的对象被称为已损坏。
“不一致状态”是什么意思?如果有人能解释一下,我将不胜感激。
我想将我的问题扩展到更低层次的视角,比如在JVM中(可能类似汇编语言),i = i + 1;这个Java语句可能会被拆分为几个较小的指令,例如像move i; add i; 将i存入内存0x0101(这只是一个例子!我完全不懂汇编语言!)
现在,如果我们调用thread.stop,它实际上会停在哪里?线程是否会在完成Java语句后停止,或者可能停在“汇编语言”的中间?如果答案是后者,那么这是否可以解释我们所说的:

这些对象被称为已损坏。

?

好的,我的问题有点混乱,希望有人能理解并解释一下。先谢谢了。


相关问题 http://stackoverflow.com/questions/7291914/java-stop-safety-a-thread-not-using-while-and-boolean-flag - Peter Lawrey
5个回答

5
"损坏的对象"是一个高级概念,它不会在JVM层面上发生。程序员通过使用锁来保护关键部分,以确保其类具有线程安全性。他的类的一个不变量是每个关键部分要么完整运行,要么根本不运行。当你stop一个线程时,一个关键部分可能已经被中断,从而破坏了不变量。此时对象就被损坏了。
停止线程还隐藏了许多其他危险,如未执行清理、未释放已获取的资源等。如果一个线程不放弃正在做的事情,没有办法使它停止而不损害整个应用程序。
实际上,每当需要运行可能需要强制中止的外部代码时,必须在单独的进程中执行,因为杀死进程至少执行操作系统级别的清理,并更好地控制损坏。

3
"Inconsistent state" 指的是数据状态,这与应用程序的相关性密切关系,它是通过使用锁/监视器等使您的应用程序线程安全而精心制作的应用程序逻辑产生的。
想象一下你有这个简单的方法:
public synchronized void doSomething() 
{
      count++;
      average = count/total;
}

这个方法和其他方法一样是同步的,因为多个线程正在使用这个对象。也许有一个

标签。
public synchronized AverageAndCount getMeasurement() 
{
   return new AverageAndCount(average, count);
}

这确保了线程不能读取不完整的测量值,即如果当前测量值正在 doSomething() 内部进行计算,则 getMeasurement() 将阻塞/等待直到完成。

现在,想象一下 doSomething() 在一个线程中运行,并且您在该线程上调用 .stop()

因此,在执行 count++; 后立即停止线程,持有的监视器将被解锁,方法终止,并且不会执行 average = count/total;

这意味着数据现在是不一致的。之后调用 getMeasurement() 的任何人现在都会得到不一致的数据。

请注意,此时发生在 Java 语句级别还是较低级别并不是很重要,无论如何,数据都可能处于无法理解的不一致状态。


2

我认为问题在于线程可能在同步块中执行多步更新对象成员的操作。如果线程突然停止,则某些更新将已经发生,但还有其他更新未完成,此时对象的状态可能使其无法使用。

我怀疑ThreadDeath处理程序是否会释放由AbstractQueuedSynchronizer支持的锁,这可能会导致应用程序陷入某种死锁。

在你的长代码序列的任何逻辑点上,你可以简单地添加:

if (Thread.interrupted())  {
    throw new InterruptedException();
}

如果确定在执行长时间运行的任务的Thread上调用了Thread.interupt(),则此时将退出执行。


2
我不是专家,但这是我认为的。如果你使用 Thread.stop(),你会引发 ThreadDeath 异常,这将导致所有监视器被释放。由于你引发了异常,你正在对事物状态施加不自然的行为。
依赖这些监视器的其他线程可能会进入不一致的情况,因为他们没有预料到这种情况。而且我认为你甚至无法预测监视器释放的顺序。

-1

停止线程的方法并不清晰。实际上,当run()方法完成或发生任何异常时,已经弃用了stop()方法来停止线程。可以通过使用布尔标志变量来实现。默认情况下为“false”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接