停止、中断、暂停和恢复 Java 线程 [英] Stop, interrupt, suspend and resume a java thread

查看:85
本文介绍了停止、中断、暂停和恢复 Java 线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

i started to read about how to stop, interrupt, suspend and resume safely a java thread, i found on oracle documentation the following solutions :

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 影响到已启动的线程线?这样做背后是否有任何秘密(例如释放使用终结器分配的资源)?

- To stop a thread i can use a boolean variable instead of volatile Thread, but why Oracle insists on affecting null to the started thread? is there any secret (e.g liberating resources allocated using finalizer) behind doing it like this?

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

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

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

- why should i create new variable moribund and not using directly 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) 因为我不明白添加它的目的是什么,我的代码可以在没有它的情况下编译并正确运行(具有相同的输出结果).

- Why inside run method they added the loop while (threadSuspended) because i don't understand what the purpose of adding it, and my code can be compiled and run correctly without it (with same output results).

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

推荐答案

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

1. Using a local Thread variable prevents other threads invoking the run() method on your object. Only the thread represented by this object instance can use the run() method. It is generally bad practice to invoke the run() method of a Thread manually from a different Thread, but certainly possible.

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

2. This point needs to be explained in the context of point 1. This part also considers the case when interval is very long, and the thread needs to be stopped ASAP.
You certainly need to nullify the reference because otherwise the code in part 1 will just continue looping. But consider what may happen if you simplify the stop method to:

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

由于这是从另一个线程执行的,因此它可以以任何方式与 run() 方法交织在一起.例如,线程A调用stop()来停止run()中的线程B:

Since this is executed from another thread, it can be intertwined with the run() method in any way. For example, threadA calls stop() to stop threadB which is in run():

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

在这种情况下,线程B不是立即停止,而是进行另一个睡眠周期,这使停止等待长时间的线程的设置任务失败.在给定的实现中,您首先取消,然后中断,这可以防止这种行为.

In this case, instead of immediately stopping, threadB does another cycle of sleeping, which fails the set task of stop a thread that waits for long periods. In the given implementation you first nullify, then interrupt, which prevents this kind of behaviour.

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

3. In short: Because another thread may have notified your code, without setting the correct flag. The general contract of notify() is that it is harmless to call (but a useless call will obviously consume some resources). All threads are supposed to be able to cope with spurious wake-ups.

这篇关于停止、中断、暂停和恢复 Java 线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆