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
相关产品推荐
相关产品推荐

