为什么这个线程的行为如此奇怪?
让我们考虑以下代码片段,其行为符合预期。线程运行,然后暂停,然后取消暂停并完成执行:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当您调用
wait()
时,您的线程将等待,直到另一个线程调用其notify()
方法。您没有从主线程中调用线程上的
notify()
。另请注意,
synchronize(this)
与同步方法相同;它使用对象本身作为锁。一旦您的线程命中wait()
,您的主线程将在thread.unpause()
上阻塞,因为checkPause()
方法拥有锁。When you call
wait()
, your thread waits until another thread calls itsnotify()
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 hitswait()
your main thread will block onthread.unpause()
because thecheckPause()
method has the lock.我看到了
wait()
,但没有看到相应的 < code>notify() 调用将再次唤醒线程。I see the
wait()
, but I don't see the correspondingnotify()
call that would wake the thread again.我认为在第一种情况下,线程根本不会暂停,因为如果没有
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 bothpause()
are called beforecheckPause()
and the Thread never waits. In the 2nd case, the thread reachescheckPause()
when pause = true and the it waits. since no one callnotify()
, it will not continue.