8

我实际上正在寻找一种更简单的方法来杀死线程,无论线程在哪里运行。但是互联网上的大多数解决方案都指向我使用布尔标志来控制线程的执行,如果我想停止线程然后将布尔变量设置为 false。

但是,如果可运行的任务是一个 LONG 线性任务,这意味着该任务不重复怎么办?在这种情况下,创建一个“while”循环来覆盖整个任务块并不容易。

使用 Thread.stop 真的很诱人,但警告“已弃用”似乎使用起来很危险。我已通读这篇文章 为什么不推荐使用 Thread.stop、Thread.suspend、Thread.resume 和 Runtime.runFinalizersOnExit?

但我无法理解

如果以前受这些监视器保护的任何对象处于不一致状态,则其他线程现在可能会查看这些处于不一致状态的对象。据说这些物体已损坏。

“不一致的状态”是什么意思?如果有人可以对此进行解释,我将不胜感激。

我想将我的问题扩展到更低级别的视图,比如说i = i + 1;在 JVM(可能是汇编语言)中,也许这个 Java 语句会被分成几个更小的指令,例如move i ; add i ; get i into memory 0x0101(这是一个例子!我完全不知道)不懂汇编语言!)

现在,如果我们调用thread.stop,它实际上会停在哪里?线程会在完成 Java 语句后停止,还是可能处于“汇编语言”的中间?如果答案是第二个,难道是我们说的理由

据说这些物体已损坏。

?

好的,我的问题有点困惑,希望有人能理解和解释。提前致谢。

4

5 回答 5

5

“损坏的对象”是一个高级概念,它不会发生在 JVM 级别。程序员通过用锁保护关键部分来设计他的类时考虑到线程安全。每个关键部分要么完全运行,要么根本不运行,这是他的类的一个不变量。当你stop一个线程时,一个临界区可能在中间被打断了,所以打断了不变量。在那一刻,物体被损坏了

停止一个线程会隐藏更多的危险,比如没有执行清理,没有释放获取的资源等。如果一个线程不放弃它正在做的事情,就没有办法在不损害整个应用程序的情况下让它停止。

在实践中,每当需要运行可能需要强制中止的外来代码时,这必须在单独的进程中完成,因为杀死一个进程至少会执行操作系统级别的清理,并且可以更好地控制损坏。

于 2012-10-31T08:53:41.867 回答
3

“不一致的状态”是指您的应用程序关心的数据状态,即您的应用程序逻辑通过使用锁/监视器等使您的应用程序线程安全而精心生成的状态。

想象一下你有这个简单的方法:

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 语句级别还是在较低级别发生这种情况都不是很相关,数据可能处于您在任何情况下都无法推理的不一致状态。

于 2012-10-31T09:05:07.613 回答
2

我不是专家,但这是我的想法。如果你使用Thread.stop()你会导致ThreadDeath异常,这将导致所有监视器被释放。由于您引发了异常,因此您将不自然的行为应用于事物的状态。

依赖这些监视器的其他线程可能会进入不一致的情况,因为他们没有预料到。而且我认为您甚至无法预期显示器发布订单。

于 2012-10-31T08:56:41.740 回答
2

我认为担心的是线程可能处于同步块的中间,对对象的成员执行多步更新。如果线程突然停止,那么会发生一些更新,但不会发生其他更新,现在对象的状态可能会使其无法使用。

我怀疑 ThreadDeath 处理是否会释放一个由它Lock支持的AbstractQueuedSynchronizer可能会使应用程序陷入某种死锁的路径。

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

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

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

于 2012-10-31T08:58:02.357 回答
-1

停止线程的方法不清楚。实际上,只要 run() 方法完成或发生任何异常,线程就会停止。通过使用布尔标志变量。默认情况下,不推荐使用 stop() 方法。默认为“false”

于 2013-06-18T08:07:35.557 回答