SourceDataLine.drain()在OSX上挂起

我的游戏通过常用方法播放声音:

sdl.open(); sdl.start(); sdl.write(data, 0, data.length); sdl.drain(); sdl.stop(); sdl.close(); 

用户可以取消播放(异步):

 sdl.stop(); 

这种取消在Windows下运行良好,但是对于一个运行带有Java 6的OSX 10.5.8的用户,程序会挂起。 Threaddump显示回放线程在drain()中: com.sun.media.sound.MixerSourceLine.nDrain 。 如果用户没有中断声音,它会很好地完成并继续应用程序。

我的问题是:

  • 这是OSX Java的错误吗?
  • 我应该使用sdl.close()而不是停止吗?
  • 有关变通方法的任何建议或经验吗?

编辑 :我发现此错误报告具有类似的效果,但页面说它已修复。

作为参考,这个使用close()例子通常在Java 5或6下退出。

除非在初始线程上已经正常关闭了line ,否则在EDT上调用stop()而不是close()挂起Java 5和6。 这似乎是drain()阻塞的预期结果,因为停止的线不能消耗。

 import java.awt.EventQueue; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; import javax.swing.JOptionPane; /** * @see https://stackoverflow.com/questions/7803310 * @see https://stackoverflow.com/questions/2065693 */ public class Tone { public static void main(String[] args) throws LineUnavailableException { final AudioFormat af = new AudioFormat(Note.SAMPLE_RATE, 8, 1, true, true); final SourceDataLine line = AudioSystem.getSourceDataLine(af); EventQueue.invokeLater(new Runnable() { public void run() { JOptionPane.showMessageDialog(null, "Halt"); //line.stop(); // stops and hangs on drain line.close(); } }); line.open(af, Note.SAMPLE_RATE); line.start(); for (Note n : Note.values()) { play(line, n, 500); play(line, Note.REST, 10); } line.drain(); line.close(); } private static void play(SourceDataLine line, Note note, int ms) { ms = Math.min(ms, Note.SECONDS * 1000); int length = Note.SAMPLE_RATE * ms / 1000; int count = line.write(note.data(), 0, length); } } 

需要Note