我知道这是一个常见问题,但我找不到针对我的特定情况的解决方案。
我有一个 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]);
。有什么建议吗?
提前致谢
最佳答案
由于 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()了解详情。
关于Java线程第二次不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24845402/