简体   繁体   中英

Why does this Thread behave so strange?

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 :/

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.

我看到了wait() ,但是没有看到相应的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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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