【问题标题】:How Java thread.stop() work?Java thread.stop() 如何工作?
【发布时间】:2012-10-31 08:41:18
【问题描述】:

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

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

使用 Thread.stop 确实很诱人,但“已弃用”警告似乎使用起来非常危险。我已通读这篇文章 Why Are Thread.stop, Thread.suspend, Thread.resume and Runtime.runFinalizersOnExit Deprecated?

但我看不懂

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

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

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

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

据说这样的物体已经损坏了。

?

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

【问题讨论】:

标签: java multithreading


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

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

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

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

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

        【讨论】:

          【解决方案5】:

          停止线程的方法并不明确。实际上,当 run() 方法完成或发生任何异常时,不推荐使用 stop() 方法,然后线程停止。通过使用布尔标志变量。默认为“false”

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-07-05
            • 2013-05-06
            • 1970-01-01
            • 2016-05-19
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多