当前位置: 首页 > 知识库问答 >
问题:

等待() 和通知() 与线路侦听器

太叔凌龙
2023-03-14

因为这是我的第一篇文章,所以我为它的结构上的任何错误道歉。我正在做一个个人项目,这是一个用java制作的时钟,可以显示时间/日期/日期,每季度播放一个音频文件,以及报时。图形用户界面是用摆动项构建的。

当时钟到达一定时间时,它必须发出钟声/播放声音,我希望在时钟响起时在GUI上显示一个图标。此时,图标在方法的开头切换,在方法的结尾再次切换。在第二次切换图标之前,我希望方法在播放音频时等待()。(也许有更好的方法来做到这一点。)

我没有使用java的经验,我觉得我使用的wae()和通知()不正确。我看了很多例子,直到我头晕目眩,我仍然不确定我需要的解决方案。

我正在使用线路侦听器通知剪辑已完成播放,并可以继续切换图标。

这是播放钟声的方法:

public void play() throws InterruptedException {
    while (mute == false) {
        synchronized (chimeLock) {
            ChimeClockGUI.toggleChimeIcon();
            clip.start();
            do {
                chimeLock.wait();
            } while (clip.isActive());
            ChimeClockGUI.toggleChimeIcon();
        }
    }
}

public void toll() throws InterruptedException {
    if (mute == false) {
        synchronized (chimeLock) {
            ChimeClockGUI.toggleChimeIcon();
            ONTHEHOUR.clip.start();
            do {
                chimeLock.wait();
            } while (ONTHEHOUR.clip.isActive());
            if (Calendar.getInstance().get(Calendar.HOUR) == 0) {
                clip.loop(11);
                do {
                    chimeLock.wait();
                } while (clip.isActive());
            } else if (Calendar.getInstance().get(Calendar.HOUR) == 1) {
                clip.start();
                do {
                    chimeLock.wait();
                } while (clip.isActive());
            } else {
                clip.loop(Calendar.getInstance().get(Calendar.HOUR) - 1);
                do {
                    chimeLock.wait();
                } while (clip.isActive());
            }
            ChimeClockGUI.toggleChimeIcon();
        }
    }
}

最后,LineListener中的update()方法:

@Override
public void update(LineEvent le) {
    synchronized (chimeLock) {
        LineEvent.Type type = le.getType();
        if (type == LineEvent.Type.OPEN) {
            System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                    .format(new Timestamp(System.currentTimeMillis())) + ": Clip opened...");
        } else if (type == LineEvent.Type.CLOSE) {
            System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                    .format(new Timestamp(System.currentTimeMillis())) + ": Clip closed...");
            chimeLock.notifyAll();
        } else if (type == LineEvent.Type.START) {
            System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                    .format(new Timestamp(System.currentTimeMillis())) + ": Clip started...");
        } else if (type == LineEvent.Type.STOP) {
            System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                    .format(new Timestamp(System.currentTimeMillis())) + ": Clip stopped...");
            chimeLock.notifyAll();
        }
    }
}

我包括调用play()和toll()的方法。

chimeService.scheduleAtFixedRate(() -> {
    try {
        ChimeClockSound.TOLL.toll();
        } catch (InterruptedException ex) {
            Logger.getLogger(ChimeClockGUI.class.getName())
                  .log(Level.SEVERE, null, ex);
    }

非常感谢任何帮助或建议。谢谢大家!

共有1个答案

林祯
2023-03-14

这里的第一个问题是clip。在数据实际开始加载之前,isRunning()返回false,因此应确保始终使用do-while循环调用wait()

do {
    wait();
} while (clip.isRunning());

最好在一个专用的锁对象上调用etc/通知,而不是在类的整个实例上。这样,的其他使用等待/通知不会干扰,您的方法不需要同步,这会减慢速度。

private final Object chimeLock = new Object();

这样,您可以将< code>wait()替换为:

synchronized (chimeLock) {
    chimeLock.wait();
}

...并将< code>notifyAll()替换为:

synchronized (chimeLock) {
    chimeLock.notifyAll();
}

...并从方法声明中删除已同步,因为它现在正在锁定对象上同步。

要记住的最后一件事是,中断异常仅在线程中断时才会被抛出,这通常意味着某些东西(如JVM)希望线程停止运行。当你发现这一点时,你应该把事情包起来并尽快返回。

 类似资料:
  • 问题内容: 在MySQL中是否有等效于PostgresQL的notify和listen?基本上,我需要在Java应用程序服务器中监听触发器。 问题答案: 不,还没有像这样的内置函数。您需要使用诸如“ read” 0/1之类的预制标志进行选择来“ ping”(每1-5秒)数据库。后 用read = 1更新它

  • 我有一段代码 如您所见,我首先将标志设置为false,这样其中一个线程就可以进入Sum2Elements方法并将其更改为true,从而让所有人都等待。 我知道在同步代码中,只有一个线程可以完成它的任务,这里我有两个同步方法,这是否意味着两个线程在每次通知之后都在尝试执行这个方法? 如果是这样,那么一个线程是否不可能输入Sum2Elements,在另一个线程进入InsertElement之前将标志更

  • 问题内容: 与传统的等待通知机制相比,使用Condition接口/实现的优点是什么?在这里,我引用道格·李(Doug Lea)的评论: 条件将对象监视方法(wait,notify和notifyAll)分解为不同的对象,从而通过与任意Lock实现结合使用,从而使每个对象具有多个等待集。如果Lock替换了同步方法和语句的使用,而Condition替换了Object监视器方法的使用。 我看到这是实现等待

  • 我正在尝试创建一个应用程序,使用新的Android服务来读取所有通知,也可以删除它们,但它并不起作用。在我的舱单上: 我有一个类NotificationListener扩展了NotificationListenerService我重写了两个方法OnNotificationPost(StatusBarNotification sbn)、onNotificationRemoved(StatusBarN

  • 我想做一个小练习来习惯等待/通知。我想做的是简单地启动一个线程,然后用等待让它进入睡眠状态,用通知唤醒它,多次。 我的代码是: 我希望这会是这样 相反,这样做: 所以。。。通知似乎没有唤醒打印机线程? 这不应该是一个死锁,因为通过等待,我释放了所有的锁,所以主服务器不应该有任何对打印机的锁,打印机应该能够唤醒并打印。 我做错了什么?

  • 我有一个控制器类,它需要为列表中的每个项目执行各种异步操作: 对于每个A 播放音频并等待完成 等t秒 对于A的每个子部分B: 播放音频并等待 等待t2秒 当我的方法被激发。我试着回复听众: 但最后我还是无法摆脱内部循环,这让我觉得整个想法都行不通。我已经查看了未来的界面,但这似乎也不是我想要的。 我知道我可以用一堆变量来解决这个问题,以跟踪我在状态流中的位置,但是带有一些框架的循环会更干净。谢谢: