-1

我正在创建一个使用声音的 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);
                    }
                });

暂时忘记哈希图来缓存 AudioClips,这没有任何区别。所谓的下面的代码,比如说,连续 10 次,导致 Java 疯狂大约 10 秒。

                AudioClip soundClip = new AudioClip(url.toString());
                soundClip.play(soundVolume);

这可以正常工作(就像互联网上的 5.000.000 个示例一样),但是在 play() 之后它会疯狂地产生线程(和滞后);方法被调用(每个悬停/调用数百个线程(如前所述))。

4

1 回答 1

0

我认为您的代码中的其他地方有问题。我已将您的描述提炼为这个(诚然简单化)示例:

@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();
}

在第 10 秒处观看 Java Mission Control,我看到一次创建了 100 个线程。然而,他们都立即死亡(他们已经播放了短暂的警报声并完成了)。因此,“Live Thread”图表上升了 100 个线程,然后在几秒钟内又回到了原来的位置。

您的代码中的其他地方是否存在占用资源或线程引用的内容?这是我试图找出为什么要成倍增加的最佳建议。

于 2018-01-18T18:17:02.957 回答