java - 停止、中断、挂起和恢复 Java 线程

标签 java multithreading resume suspend

我开始阅读有关如何安全地停止、中断、挂起和恢复 java 线程的内容,我在 oracle 文档中找到了以下解决方案:

1- 如何安全地停止线程:

private volatile Thread blinker;

public void stop() {
    blinker = null;
}

public void run() {
    Thread thisThread = Thread.currentThread();
    while (blinker == thisThread) {
        try {
            Thread.sleep(interval);
        } catch (InterruptedException e){
        }
        repaint();
    }
}

- 要停止线程,我可以使用 boolean 变量而不是 volatile Thread,但为什么 Oracle 坚持将 null 影响到启动线?这样做背后有什么 secret (例如,释放使用终结器分配的资源)吗?

2- 如何中断等待很长时间的线程:

public void stop() {
    Thread moribund = waiter;
    waiter = null;
    moribund.interrupt();
}

- 为什么我应该创建新变量 moribund 而不是直接使用 waiter.interrupt()

3- 如何暂停和恢复线程:

private volatile boolean threadSuspended;

public void run() {
    while (true) {
        try {
            Thread.sleep(interval);

            if (threadSuspended) {
                synchronized(this) {
                    while (threadSuspended)
                        wait();
                }
            }
        } catch (InterruptedException e){
        }
        repaint();
    }
}

public synchronized void mousePressed(MouseEvent e) {
    e.consume();

    threadSuspended = !threadSuspended;

    if (!threadSuspended)
        notify();
}

- 为什么在 run 方法中他们添加了循环 while (threadSuspended) 因为我不明白添加它的目的是什么,并且我的代码可以在没有它的情况下正确编译和运行(具有相同的输出结果)。

来源链接 http://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

最佳答案

1. 使用本地 Thread 变量可防止其他线程调用您对象上的 run() 方法。只有这个对象实例代表的线程才能使用run()方法。从不同的 Thread 手动调用 Threadrun() 方法通常是不好的做法,但肯定有可能。

2. 这一点需要在第1点的上下文中进行解释。这部分还考虑了interval很长的情况,需要尽快停止线程。
您当然需要使引用无效,否则第 1 部分中的代码将继续循环。但是考虑一下如果将 stop 方法简化为:

可能会发生什么
public void stop() {
    waiter.interrupt();
    waiter = null;    
}

因为这是从另一个线程执行的,所以它可以以任何方式与 run() 方法交织在一起。例如,threadA调用stop()停止在run()中的threadB:

  1. 线程B: sleep (间隔)
  2. threadA: waiter.interrupt()
  3. threadB: 捕获到 InterruptedException
  4. threadB:调用重绘
  5. 线程B:进入下一个while循环
  6. 线程B:进入休眠(间隔)
  7. threadA: 服务员 == null

在这种情况下,threadB 没有立即停止,而是进行了另一个 sleep 周期,这未能完成 停止等待很长时间的线程 的设置任务。在给定的实现中,您首先取消,然后中断,这可以防止这种行为。

3. 简而言之:因为另一个线程可能已经通知了您的代码,但没有设置正确的标志。 notify()的一般约定是调用是无害的(但是无用的调用显然会消耗一些资源)。所有线程都应该能够应对虚假唤醒。

关于java - 停止、中断、挂起和恢复 Java 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23795360/

相关文章:

java - 将 Java 客户端 (JMS) 连接到 IBM MQ 时出现问题

c++ - 我想知道系统调用()被中断时到达的是哪个信号

objective-c - 客观的: @synchronized how does it work [duplicate]

java - 在 Java 上处理 MySQL 查询时处理断电?

android - 恢复 Activity 安卓

java - 将应用程序升级到 Spring 3.0 可能存在哪些痛点

java - (可能很奇怪)长增量行为?

java - 使用附加接口(interface)实现在 Java 中实例化匿名内部类

java - 线程 hibernate 直到收到另一个类的通知

ios - 在 App 重新进入时恢复 UIView 动画?