为什么这个Thread表现得如此奇怪?

时间:2011-03-26 01:31:40

标签: java multithreading

让我们想一想下面的代码片段,它的行为符合预期。线程运行,然后暂停,然后取消暂停并完成执行:

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
    }

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

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

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

这里是overriden run方法的实现:

@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()方法结束。然后它等待:/

3 个答案:

答案 0 :(得分:3)

当你调用wait()时,你的线程会等到另一个线程调用它的notify()方法。

你没有在主线程的线程上调用notify()

另请注意,synchronize(this)与同步方法相同;它使用对象本身作为锁。一旦你的帖子点击wait(),你的主线程就会在thread.unpause()上阻止,因为checkPause()方法有锁定。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

我认为在第一种情况下,线程根本不会暂停,因为如果没有Thread.sleep(500);,可能在pause()之前调用checkPause()并且线程永远不会等待的时间。在第二种情况下,当pause = true并且它等待时,线程达到checkPause()。因为没有人打电话notify(),所以不会继续。