Java声音API在播放音频文件后将其锁定

Java声音API在播放音频文件后将其锁定,java,audio,javasound,Java,Audio,Javasound,我正在尝试使用Javax.sound来播放.wav文件。 一切正常,文件按预期播放,最后我关闭剪辑并关闭音频输入流。但是,在此之后,该文件仍处于锁定状态(正在使用中),我无法触摸它而不出现异常:java.nio.file.FileSystemException:alerting.wav:该进程无法访问该文件,因为另一个进程正在使用它 代码示例如下: static private class SoundThread extends Thread implements LineListener {

我正在尝试使用Javax.sound来播放.wav文件。 一切正常,文件按预期播放,最后我关闭剪辑并关闭音频输入流。但是,在此之后,该文件仍处于锁定状态(正在使用中),我无法触摸它而不出现异常:java.nio.file.FileSystemException:alerting.wav:该进程无法访问该文件,因为另一个进程正在使用它

代码示例如下:

static private class SoundThread extends Thread implements LineListener {
    private boolean playCompleted;
    private int cycles;
    
    public SoundThread(int repeats) {
        cycles = repeats;
    }
    
    @Override
    public void run() {
        Clip clip;
        AudioInputStream inputStream;
        File soundFile = new File("alerting.wav");
        try {
            inputStream = AudioSystem.getAudioInputStream(soundFile);
            try {
                clip = AudioSystem.getClip();
                clip.addLineListener(this);
                clip.open(inputStream);
                while(cycles > 0) {
                    playCompleted = false;
                    clip.setFramePosition(0);
                    clip.start();
                    while(!playCompleted) {
                        Thread.sleep(1000);
                    }
                    Thread.sleep(audioRepeatTime * 1000);
                    cycles--;
                }
                //clip.drain();
                clip.close();
                inputStream.close();
                System.out.println("All closed");
                try {
                    this.finalize();
                } catch (Throwable ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
            } catch (Exception ex) {
                Main.syslog(Level.WARNING, "E1001 could not play alert sound", ex);
            } finally {
                inputStream.close();
            }
        } catch (UnsupportedAudioFileException ex) {
            Main.syslog(Level.WARNING, "E1001 could not play alert sound", ex);
        } catch (IOException ex) {
            Main.syslog(Level.WARNING, "E1001 could not play alert sound", ex);
        }
    }

    @Override
    public void update(LineEvent event) {
        LineEvent.Type type = event.getType();
        
        System.out.println("Event: " + type);
        if(type == LineEvent.Type.STOP) {
            playCompleted = true;
        } else if (type == LineEvent.Type.CLOSE) {
            System.out.println("listener closed");
        }
    }
}

public static void PlayAlertSound() {
    if(enableAudio) {
        SoundThread st = new SoundThread(audioLoops);
        st.start();
    }
} 

public static void PlayAlertSound(int repeats) {
    if(enableAudio) {
        SoundThread st = new SoundThread(repeats);
        st.start();
    }
} 
在Java线程列表中,我看到“Java声音事件调度器”正在运行。我想这就是文件被锁定的原因。
你知道我该怎么解决这个问题吗?感谢API提供的剪辑状态:

请注意,某些行一旦关闭,就无法重新打开。试图 重新打开此行将始终导致
LineUnavailableException

我将提出一些额外的建议

加载音频资源的更好方法是使用
class.getResource
方法,而不是使用
File
。此方法返回一个
URL
,然后可以将其作为参数传递给
AudioSystem.getAudioInputStream
方法

我不清楚您想做什么,但我也建议您对代码做一些进一步的更改。通常不使用相同的方法初始化和播放
剪辑
,因为这违背了
剪辑
的预期用途。
剪辑
用于存储可存储的声音。因此,将
Clip
作为实例变量。然后,用自己的方法放置加载并打开
剪辑的代码。并将调用
start
loop
的代码放在一个或多个单独的方法中,并且不要在播放结束时关闭
剪辑
,除非您确定不再播放它


如果您使用
clip.loop
,就不必为侦听器和计算迭代次数而烦恼。

谢谢您的回答。我在播放声音方面没有任何问题,效果很好。我的问题是,当我不播放声音并且所有内容都关闭时,文件仍然被系统锁定,无法修改或删除。我只想能够在其他对话框窗口中加载不同的.wav格式的计算机,并将其保存为与初始文件相同的名称。虽然我关闭了文件,但看起来AudioInputStream仍然锁定该文件。我也尝试过使用Media和MediaPlayer,但同样的情况也发生了。也许文件命令仍然有效。尝试改用URL。我刚注意到你做的每件事都在一条“合理的线索”之内。很少需要处理声音——每次播放声音时都会启动新线程。对不起,我帮不了你,但是你做事的方式让我很困惑。我认为简化会大大有助于解决你的问题。也许试着制作一个简单的剪辑,调用它,播放它,让它被垃圾收集,然后看看你是否可以加载文件。我知道我在过去多次加载wav文件,但总是使用自己的音频输入流。这是非常复杂程序的一部分,不是声音播放器。这就是我使用线程的原因。程序必须运行并完成它的工作,有时它必须在不保持整个程序的情况下,以一些可配置的间隔按编程次数播放声音。然而,我试着只播放一次没有线的声音。一旦文件被播放,它将被“其他进程使用”,并且不能再被触摸。谢谢这和这个话题是一样的:它从来没有得到正确的答案