栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

使用“ notify()”和“ wait()”代替“ suspend()”和“ resume()”来控制线程

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用“ notify()”和“ wait()”代替“ suspend()”和“ resume()”来控制线程

您误解了

wait()
工作原理。调用
wait
一个对
Thread
对象不会暂停该线程;
相反,它告诉当前正在运行的线程等待其他事件发生。为了解释原因,我需要备份一点并解释
synchronized
实际的作用。

输入

synchronized
块时,将获得与对象关联的 监视器 。例如,

synchronized(foo) {

获取与对象关联的监视器

foo

一旦有了监视器,在退出同步块之前,没有其他线程可以获取它。这是

wait
notify
进来。

wait
是Object类上的一种方法,该方法告诉当前正在运行的线程临时释放其持有的监视器。这允许其他线程在上同步
foo

foo.wait();

该线程将不会继续,直到其他人调用

notify
notifyAll
打开
foo
(或线程被中断)。一旦发生这种情况,该线程将尝试重新获取监视器
foo
,然后继续。请注意,如果有任何其他线程在等待获取监视器,那么它们可能会首先进入-
无法保证JVM将分发锁的顺序。请注意,
wait()
如果没有人致电
notify
或,它将永远等待
notifyAll
。通常最好使用
wait
超时的其他形式。当有人呼叫
notify
/
notifyAll
或超时到期时,该版本将被唤醒。

因此,您需要一个线程来进行等待,而另一个线程来进行通知。双方

wait
notify
必须持有他们试图等待或通知的对象监视器;
这就是为什么您看到IllegalMonitorStateException的原因。

一个示例可以帮助您理解:

class RepaintScheduler implements Runnable {    private boolean paused = false;    private final Object LOCK = new Object();    public void run() {        while (true) { synchronized(LOCK) {     if (paused) {         try {  LOCK.wait();         } catch (InterruptedException e) {  e.printStackTrace();         }     } else {         repaint();     } } try {     Thread.sleep(20); } catch (InterruptedException e) {     e.printStackTrace(); }        }    }    public void pause() {        synchronized(LOCK) { paused = true; LOCK.notifyAll();        }    }    public void resume() {        synchronized(LOCK) { paused = false; LOCK.notifyAll();        }    }}

然后,您的Applet代码可以执行以下操作:

public void init() {    RepaintScheduler scheduler = new RepaintScheduler();    // Add listeners that call scheduler.pause and scheduler.resume    btn_increment.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {        scheduler.resume();    }});    btn_decrement.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {        scheduler.pause();    }});    // Now start everything up    Thread t = new Thread(scheduler);    t.start();}

请注意,Applet类不关心调度程序如何暂停/继续并且没有任何同步块。

因此,这里可能的事件顺序是:

  • 线程A开始运行重绘计划程序。
  • 线程A进入睡眠状态20毫秒。
  • 线程B(事件分发线程)收到按钮单击;称为“暂停”。
  • 线程B在LOCK上获取监视器。
  • 线程B更新’paused’变量并调用LOCK.notifyAll。
  • 没有线程在等待LOCK,因此没有发生任何有趣的事情。
  • 线程B在LOCK上释放监视器。
  • 线程A唤醒,再次经历其循环。
  • 线程A在LOCK上获取监视器。
  • 线程A认为应该暂停它,因此它调用LOCK.wait。
  • 此时,线程A挂起,等待有人调用notifyAll。线程A在LOCK上释放监视器。
  • 一段时间后,用户单击“恢复”。
  • 线程B调用scheduler.resume。
  • 线程B在LOCK上获取监视器。
  • 线程B更新’paused’变量并调用LOCK.notifyAll。
  • 线程A看到“ notifyAll”并唤醒。它试图获取LOCK上的监视器,但是它由线程B保留,因此线程A阻塞了。
  • 线程B在LOCK上释放监视器。
  • 线程A获取监视器并继续。

这一切有意义吗?

不需要单独的LOCK变量;我这样做是为了突出您没有在

Thread
实例上调用wait /
notify的事实。同样,RepaintScheduler中的逻辑也不理想,而仅仅是说明如何使用等待/通知。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/509461.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号