让我们想一想下面的代码片段,它的行为符合预期。线程运行,然后暂停,然后取消暂停并完成执行:
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()
方法结束。然后它等待:/
答案 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()
,所以不会继续。