我知道这是一个常见的问题,但我无法找到适合我特定情况的解决方案。
我有一个class Player implements Runnable
用于在点击按钮时播放.wav声音。
以下是run()
方法。
public void run() {
auline.start();
int nBytesRead = 0;
byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];
try {
while (nBytesRead != -1) {
nBytesRead = audioInputStream.read(abData, 0, abData.length);
if (nBytesRead >= 0)
auline.write(abData, 0, nBytesRead);
}
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
auline.drain();
auline.close();
}
}
这就是我自己创建和运行线程的地方。
soundButtons[j].addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
int index = Integer.parseInt(button.getName());
Thread t = new Thread(samples[index]);
t.start();
}
});
问题是java不允许两次启动同一个线程。但我无法弄清楚为什么它不起作用,因为每次我创建一个新的参考对象new Thread(samples[index]);
。有什么建议吗?
提前致谢
答案 0 :(得分:4)
由于audioInputStream
是一个类变量而未在run()
方法中重新初始化,因此会出现以下问题。
首先致电run()
:
while
循环将从audioInputStream
读取字节,直到它为空并返回-1。
第二次致电run
:
当audioInputStream
引用同一个对象 - 一个空流 - 它将在第一次调用read(...)
时返回-1,循环将中止。
问题的一个解决方案是在每次调用run()时创建一个新的AudioInputStream。 另一种解决方案是使用流提供的mark()/ reset()功能。
像这样创建流:
InputStream src = getClass().getResourceAsStream(PATH_TO_SOUND_FILE);
InputStream buffered = new BufferedInputStream(src);
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(buffered);
audioInputStream.mark(LENGTH_OF_STREAM_IN_BYTES); // you have to specify this here.
使用BufferedInputStream非常重要。现在你可以使用
audioInputStream.reset();
在run()
方法中。
查看http://docs.oracle.com/javase/7/docs/api/javax/sound/sampled/AudioInputStream.html#reset()了解详情。