You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaSoundRecorder的TargetDataLine调用finish后无法关闭如何解决?

问题根因
  • 调用finish()方法关闭录音线后,没有手动将成员变量line置为null,而startRecording()方法中只有line == null时才会执行新的录音逻辑,导致第二次调用启动方法时直接跳过了录音流程。
  • AudioSystem.write()是阻塞方法,仅调用line.stop()、line.close()可能存在时序问题,无法立即终止write操作,导致录音线程没有正常退出。
  • 没有做非空校验,若finish()在line初始化完成前被调用,会直接抛出空指针异常。
  • 录音线程是局部变量,无法在结束时主动等待其终止,可能出现资源未释放完全就启动下一次录音的问题。
修复方案

1. 新增成员变量存储录音线程

在JavaSoundRecorder类中新增如下成员变量:

private Thread recordThread;

2. 修改finish()方法

添加非空校验、资源释放后置空line、等待录音线程终止:

/*停止录音*/
public void finish() {
    if (line != null && line.isOpen()) {
        line.stop();
        line.close();
        line = null;
    }
    // 等待录音线程终止,最多等待1秒避免卡死
    if (recordThread != null && recordThread.isAlive()) {
        try {
            recordThread.join(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        recordThread = null;
    }
}

3. 修改startRecording()方法

将局部线程变量赋值给成员变量,同时在异常分支中也增加资源释放逻辑,避免异常场景下资源泄漏:

/*捕获声音并录制为WAV文件,创建独立线程执行录音逻辑*/
protected int startRecording(String path) {
    // 启动前先释放上一次的资源,避免残留状态影响本次录音
    finish();
    setFile(new File(path));
    errorNum = 0;
    
    if(line == null) {
        recordThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 检查系统是否支持当前配置的音频线
                    if(!AudioSystem.isLineSupported(info)) {
                        System.out.println("音频格式不支持");
                        errorNum = 2;
                        return;
                    }
                    line = (TargetDataLine) AudioSystem.getLine(info);
                    line.open(audioForm);
                    line.start();

                    AudioInputStream ais = new AudioInputStream(line);
                    // 将音频流写入本地文件
                    AudioSystem.write(ais, fileType, savedWav);
                } 
                catch(LineUnavailableException e) {
                    errorNum = 3;
                    e.printStackTrace();
                } 
                catch(IOException e) {
                    errorNum = 4;
                    e.printStackTrace();
                } finally {
                    // 不管录音正常结束还是异常报错,都主动释放资源
                    if (line != null && line.isOpen()) {
                        line.stop();
                        line.close();
                        line = null;
                    }
                }
            }
        });
        recordThread.start();
    }
    return errorNum;
}

修改完成后即可正常重复调用startRecording()和finish()完成多次录音,不会出现音频线被占用的问题。

内容的提问来源于stack exchange,提问作者user16251398

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 01:24:01