简体   繁体   English

如何在Java中安全地停止和恢复线程?

[英]How to stop and resume thread safely in Java?

I have running thread that I would like to stop and later on resume at some point. 我有正在运行的线程,我想停止然后稍后再恢复。 I learned not to use stop() etc. as these are deprecated and got to this code below that seems to stop thread successfully. 我学会了不使用stop()等,因为它们已被弃用,并转到下面的代码似乎成功停止了线程。 It simply exits run method. 它只是退出运行方法。 Now, how can I restart it? 现在,如何重新启动它? If I call start() method it says that thread is still running, so would directly calling run() do in this situation? 如果我调用start()方法,它说线程仍在运行,那么在这种情况下直接调用run()可以吗? Would it cause any problems? 会引起什么问题吗? BTW this is for Android app if that makes any difference. 顺便说一句,如果有什么不同,这是针对Android应用的。

private volatile stopThread;

public void stopButton() {
    // this is called when button is clicked
    // and thread is already started and running
    stopThread= true;
}

public void run() {

    while (!stopThread) {
        // do something here
    }

    stopThread=false;
}

EDIT: its a timer that starts when thread is started, then can be paused and started again. 编辑:其计时器在线程启动时启动,然后可以暂停并重新启动。 So timer is a class containing Thread object (I already extend the class with SurfaceView). 所以timer是一个包含Thread对象的类(我已经使用SurfaceView扩展了该类)。

The only safe way to stop and resume a thread safely is to add code at the relevant points in the thread's body to deal with it. 安全地停止和恢复线程的唯一安全方法是在线程主体的相关点添加代码以对其进行处理。 (Don't use the deprecated Thread stop / pause / resume because they are fundamentally unsafe.) (不要使用已弃用的线程停止/暂停/继续,因为它们从根本上来说是不安全的。)

Stop without resumption is relatively simple, using either an application-specific flag, or the Thread.interrupt() mechanism. 使用特定于应用程序的标志或Thread.interrupt()机制,无需恢复即可停止是相对简单的。 The latter is probably better because some of Java's synchronization and IO APIs are interrupt-aware. 后者可能更好,因为某些Java的同步和IO API具有中断感知能力。 However, you do run against the problem that a lot of existing libraries are not interrupt aware, or don't deal with InterruptedException properly. 但是,您确实遇到了很多现有库不支持中断的问题,或者没有正确处理InterruptedException

Stop with resumption is more tricky. 停止恢复是比较棘手的。 You'll need to create your own class something like this: 您需要创建自己的类,如下所示:

public class PauseControl {
    private boolean needToPause;

    public synchronized void pausePoint() {
        while (needToPause) {
            wait();
        }
    }

    public synchronized void pause() {
        needToPause = true;
    }

    public synchronized void unpause() {
        needToPause = false;
        this.notifyAll();
    }
}

and add calls to myPauseControl.pausePoint() at relevant points throughout your the thread's code. 并在整个线程代码的相关点添加对myPauseControl.pausePoint()调用。 Note that this won't allow you to pause IO, or activity in "child" threads, and it will only pause at points in your code where you call the pausePoint method. 请注意,这将不允许您暂停IO或“子”线程中的活动,并且只会在代码中调用pausePoint方法的点处暂停。 Also you need to beware of creating problems by pausing the thread while it holds locks on something else, or while something else is waiting for it to respond. 另外,您还需要提防通过在线程保持对其他对象的锁定或等待其他对象响应时暂停线程来创建问题。

The Java 1.4 docs explained why and gave alternatives to the various deprecated Thread methods, including suspend() and resume() by using wait() and notify() instead. Java 1.4文档解释了原因,并通过使用wait()notify()代替了各种不赞成使用的Thread方法,包括suspend()resume()

Look for the heading What should I use instead of Thread.suspend and Thread.resume? 寻找标题而不是Thread.suspend和Thread.resume应该使用什么? about halfway down the page. 大约在页面的一半。

The stop() method of Thread class is deprecated and unsafe for use, because stopping a Thread causes it to unlock all monitors that it had locked. 不推荐使用Thread类的stop()方法,该方法不安全,因为停止Thread会导致它解锁所有已锁定的监视器。 This has damaging consequences, because any of the Objects (previously protected by monitors) in an inconsistent state may now be viewed by other threads in an inconsistent state. 这具有破坏性的后果,因为处于不一致状态的任何对象(以前受监视器保护)现在可以由处于不一致状态的其他线程查看。 This behavior may be subtle and difficult to detect. 此行为可能是微妙的,难以检测。

You never invoke the run() method directly and if you stop the Thread using your volatile variable approach, the Thread would have TERMINATED. 您永远不会直接调用run()方法,并且如果使用易失变量方法停止线程,则该线程将具有TERMINATED。 In order to start the Thread perform new Thread().start() again. 为了启动线程,再次执行新的Thread()。start()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM