【问题标题】:How do I pause Threads properly with wait() and notify()如何使用 wait() 和 notify() 正确暂停线程
【发布时间】:2014-11-05 18:41:04
【问题描述】:

我想要一个类来启动一个线程并提供暂停和继续这个线程的方法。我的第一种方法是使用标志,只要值为真,它就会循环睡眠方法。类似的东西:

public class Bot {
private Thread t ;
private boolean isPaused;

public Bot(){
    t = new Thread(new Runnable(){
        @Override
        public void run() {
            while (true) {
                System.out.println("Hi");


                while(isPaused){
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    });

    t.start();
}
public void pauseBot(){
    isPaused = true;
}

public void continueBot(){
    isPaused = false;
}
}

但由于线程仍在运行并浪费 CPU,我认为这不是一个好的解决方案。使用 wait() 和 notify() 会怎样。 我查看了有关该主题的各种教程,但不知何故我无法将它们应用于我的问题。

每次我尝试它时,要么得到 IllegalMonitorStateException,要么代码停止了我的整个应用程序,而不仅仅是我想停止的线程。

我的另一个问题是:如何防止线程在关键时刻暂停,例如

Runnable r = new Runnable(){

    @Override
    public void run() {
        while(true){
            task1();
            task2();

            //Thread mustn't be stopped from here....
            task3();
            task4();
            task5();
            task6();
            task7();
            //... to here

            task8();
            task9();
            task10();
        }

    }

};

因为当 task3() .... task7() 处理在线程暂停时会过期的东西时,必须有一种方法让线程完成 task7() 直到它暂停。

我希望你能帮助我解决我的问题。 提前致谢, 弗洛尔

【问题讨论】:

标签: java multithreading wait synchronized notify


【解决方案1】:

所以这是你的 Thread 类:

public class MyThread extends Thread
{

首先,您需要一个锁对象。这个对象可以是一切,如果你使用一个现有的对象,这会占用更少的内存。如果应该暂停机器人,还要定义一个标志。

    public Object lock = this;
    public boolean pause = false;

现在,为线程定义一个pause()continue() 方法。这会设置pause 标志。

    public void pause ()
    {
        pause = true;
    }

    public void continue ()
    {
        pause = false;

这里需要唤醒线程。注意锁对象上的同步,这样你就不会得到IllegalMonitorStateException

        synchronized (lock)
        {
            lock.notifyAll();
        }
    }

不,定义一个在应该暂停线程时自动暂停线程的方法。您可以在线程可以暂停的每一刻调用它。

    private void pauseThread ()
    {
        synchronized (lock)
        {
            if (pause)
                lock.wait(); // Note that this can cause an InterruptedException
        }
    }

现在,您可以在run() 方法中定义您的线程:

    public void run ()
    {
        task1();
        task2();

        pauseThread();

        task3();
        task4();
        task5();
        task6();
        task7();

        pauseThread();

        task8();
        task9();
        task10();
    }
}

【讨论】:

  • “这可以是一切”是什么意思?
  • @jameslarge 这可以是任何对象,只要只有线程调用wait()notify()方法即可
  • 对我来说这也很奇怪。我只是不明白为什么你必须创建一个只用于同步的新对象。你不能只用“这个”代替。抱歉,但我想我需要一些关于同步对象的背景信息。谢谢你的回答顺便说一句
  • @user3187049 正如我所说的你可以使用everythung,所以这没关系,你只需要注意你只在线程中使用它作为锁对象
猜你喜欢
  • 2017-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多