由于这是我的第一篇文章,我为其结构的任何错误道歉。我正在开发一个个人项目,这是一个用java制作的时钟,用于显示时间/日期/日期,每季度播放一个音频文件以及一小时钟声。 GUI使用swing项目构建。
当时钟到达时,它必须响铃/播放声音,我希望在时钟响起的同时在GUI上显示一个图标。此时,图标在方法开头切换,并在结束时再次切换。我希望在播放音频的同时 wait()的方法在第二次切换图标之前。 (也许有更好的方法来做到这一点。)
我对java缺乏经验,感觉好像我正在使用 wait()和 notify()。我看了一些例子,直到我的头旋转,我仍然不确定我需要的解决方案。
我正在使用 LineListener 来通知剪辑已完成播放,并可以继续切换图标。
这是播放钟声的方法:
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);
}
非常感谢任何帮助或建议。谢谢!
答案 0 :(得分:0)
这里的第一个问题是clip.isRunning()
返回false
直到数据实际开始加载,因此您应该确保始终使用do-while循环调用wait()
:
do {
wait();
} while (clip.isRunning());
最好在专用锁对象上调用wait
/ notify
,而不是在类的整个实例上调用。这样,wait
/ notify
的其他用途不会干扰,您的方法也不一定是synchronized
,这可能会减慢速度。
private final Object chimeLock = new Object();
使用此功能,您可以将wait()
替换为:
synchronized (chimeLock) {
chimeLock.wait();
}
...并将notifyAll()
替换为:
synchronized (chimeLock) {
chimeLock.notifyAll();
}
...并从方法声明中删除synchronized
,因为它现在正在锁定对象上进行同步。
要记住的最后一件事是InterruptedException
仅在线程被中断时抛出,这通常意味着某些东西(如JVM)希望线程停止运行。当你抓住这个时,你应该把事情包起来并尽快返回。