为什么这个线程的行为如此奇怪?

发布于 2024-10-27 16:40:44 字数 1993 浏览 1 评论 0原文

让我们考虑以下代码片段,其行为符合预期。线程运行,然后暂停,然后取消暂停并完成执行:

public static void main(final String[] args) throws InterruptedException {
        Executor exec = Executors.newSingleThreadExecutor();
        MyThread thread = new MyThread();
        exec.execute(thread);
        thread.pause();
        thread.pause(); // unpause
    }

现在让我们向线程添加一些睡眠,以便暂停一段时间:

public static void main(final String[] args) throws InterruptedException {
        Executor exec = Executors.newSingleThreadExecutor();
        MyThread thread = new MyThread();
        exec.execute(thread);
        thread.pause();
        Thread.sleep(500); 
        thread.pause(); // unpause
    }

但是该代码永远不会完成。为什么?

这是暂停方法的实现,它检查私有布尔字段是否暂停:

public synchronized void pause() {
        paused = (paused) ? false : true;
    }

这是重写运行方法的实现:

@Override
    public void run() {
        // don't worry, I just need som dummy data to take some cpu time ;)
        PriorityQueue<Double> queue = new PriorityQueue<Double>();
        Random random = new Random(System.currentTimeMillis());
        System.out.println("I stared");
        checkPause();
        // let's do some big computation
        for (int i=0; i<10000000; i++) { // 10 mio
            System.out.println(i);
            queue.add(random.nextDouble());
            if (i % 3 == 0) {
                queue.poll(); // more complex operation
            }
        }
        System.out.println("I'm done");
    }

private void checkPause() {
        synchronized (this) {
            if (paused) {
                while (paused != false) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

当我尝试调试时,我将以 wait() 方法结束。然后就等待:/

Let's think of following code fragment, that behaves as expected. Thread runs, then it's paused and then it's unpaused and finishes it's execution:

public static void main(final String[] args) throws InterruptedException {
        Executor exec = Executors.newSingleThreadExecutor();
        MyThread thread = new MyThread();
        exec.execute(thread);
        thread.pause();
        thread.pause(); // unpause
    }

Now let's add add some sleeping to thread so it's paused for a while:

public static void main(final String[] args) throws InterruptedException {
        Executor exec = Executors.newSingleThreadExecutor();
        MyThread thread = new MyThread();
        exec.execute(thread);
        thread.pause();
        Thread.sleep(500); 
        thread.pause(); // unpause
    }

But that code never finishes. Why ?

Here's implementation of pause method, it checks private boolean field for pausing:

public synchronized void pause() {
        paused = (paused) ? false : true;
    }

And here is implementation of overriden run method:

@Override
    public void run() {
        // don't worry, I just need som dummy data to take some cpu time ;)
        PriorityQueue<Double> queue = new PriorityQueue<Double>();
        Random random = new Random(System.currentTimeMillis());
        System.out.println("I stared");
        checkPause();
        // let's do some big computation
        for (int i=0; i<10000000; i++) { // 10 mio
            System.out.println(i);
            queue.add(random.nextDouble());
            if (i % 3 == 0) {
                queue.poll(); // more complex operation
            }
        }
        System.out.println("I'm done");
    }

private void checkPause() {
        synchronized (this) {
            if (paused) {
                while (paused != false) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

When I tried debugging, I'll end on wait() method. Then it just waits :/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

ぃ双果 2024-11-03 16:40:44

当您调用 wait() 时,您的线程将等待,直到另一个线程调用其 notify() 方法。

您没有从主线程中调用线程上的 notify()

另请注意,synchronize(this) 与同步方法相同;它使用对象本身作为锁。一旦您的线程命中 wait(),您的主线程将在 thread.unpause() 上阻塞,因为 checkPause() 方法拥有锁。

When you call wait(), your thread waits until another thread calls its notify() method.

You're not calling notify() on the thread from your main thread.

Also note that synchronize(this) is the same thing as synchronizing the method; it's using the object itself as the lock. Once your thread hits wait() your main thread will block on thread.unpause() because the checkPause() method has the lock.

沉溺在你眼里的海 2024-11-03 16:40:44

我看到了 wait(),但没有看到相应的 < code>notify() 调用将再次唤醒线程。

I see the wait(), but I don't see the corresponding notify() call that would wake the thread again.

孤蝉 2024-11-03 16:40:44

我认为在第一种情况下,线程根本不会暂停,因为如果没有 Thread.sleep(500);,可能两个 pause() 都是在 checkPause() 之前调用,线程永远不会等待。在第二种情况下,当pause = true时,线程到达checkPause()并等待。由于没有人调用 notify(),因此不会继续。

I think that in the 1st case, the thread doesn't pause at all, because if there is no Thread.sleep(500);, probably both pause() are called before checkPause() and the Thread never waits. In the 2nd case, the thread reaches checkPause() when pause = true and the it waits. since no one call notify(), it will not continue.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文