我正在创建一个JavaFX应用程序,该应用程序使用声音例如按钮悬停。我创建了一个JavaFX AudioClip来创建和播放声音。到目前为止,它工作正常(意思是:我听到了声音)。
当调用 play(); 方法时,声音会立即播放。如果我将鼠标悬停按钮 10 次,我会听到声音 10 次。 但是:在后台,当play()方法返回时,JavaFX会创建数百个线程(每次调用数百个线程)。我什至看不到它到底是什么,因为有这么多,Eclipse 甚至没有正确显示它们(只有一个白色区域和一个疯狂的上下跳跃滚动条)。
这会导致巨大的滞后,我不明白 JavaFX 在这里做什么!它总是相同的声音,所以我确实已经将其缓存到哈希图中,但问题不在于实例化 AudioClip,当 play() 方法返回时它显然是堆叠的。
我已经研究了几个小时,但我找不到减少滞后的解决方法(除了可能减小声音文件的大小,我做到了)。
final AudioClip soundClip;
if (audioClipCache.get(url.toString()) != null) {
// Log.info("Playing sound from cache...");
soundClip = audioClipCache.get(url.toString());
} else {
// Log.info("Caching sound...");
soundClip = new AudioClip(url.toString());
audioClipCache.put(url.toString(), soundClip);
}
Platform.runLater(new Runnable() {
@Override
public void run() {
soundClip.play(soundVolume);
}
});
暂时忘记哈希图以缓存音频剪辑,这没有任何区别。所谓的以下代码,比如连续 10 次,导致 Java 疯狂大约 10 秒。
AudioClip soundClip = new AudioClip(url.toString());
soundClip.play(soundVolume);
这应该工作(就像互联网上的 5.000.000 个示例一样),但它在 play() 之后疯狂地产生线程(和滞后);方法被调用(每个悬停/调用数百个线程(如描述))。
我认为您在代码中的其他地方遇到了问题。我已经将您的描述提炼为这个(诚然简单化)示例:
@Override
public void start(Stage arg0) throws Exception
{
Thread.sleep(10000);
AudioClip audioClip = new AudioClip(Paths.get("src/main/resources/stackoverflow/audio/alert.wav").toUri().toString());
for (int i = 0; i < 100; i++)
{
int volume = i;
Platform.runLater(() -> audioClip.play(volume));
Thread.sleep(10);
}
arg0.show();
}
在十秒处观察Java Mission Control,我看到100个线程同时被创建。但是,它们都会立即死亡(它们已经播放了简短的警报声音并完成了)。因此,"实时线程"图形会上升 100 个线程,然后在几秒钟内立即下降到原来的位置。
代码中的其他地方是否有保留资源或线程引用的内容?这是我试图找出你为什么倍增的最佳建议。