[英]Thread.interrupt() ignored
我正在尝试编写一种算法来计算声卡输入的音量。 尽管这(或多或少)不是问题,但在执行多任务处理时遇到了麻烦。 我从另一个线程调用的中断似乎被忽略了。
我之前开发过多线程环境,我想我知道Thread.isInterrupted()
与Thread.interrupted()
和InterruptedException
的陷阱-这就是为什么我仅使用Thread.isInterrupted()
的原因。 编辑 :另外,我认为我在这里使用的任何东西都不会抛出InterruptedException
。
所以我写了这个课:
import javax.sound.sampled.*;
public class SoundListener extends Thread {
/**
* RMS refresh rate in Hz (1000ms / RESPONSE_TIME)
*/
private static final int REFRESH_RATE = 40;
private final SoundMeter SOUNDMETER;
private final AudioFormat AUDIO_FORMAT;
private final int BUFFER_SIZE;
private final boolean IS_24_BITS;
private final TargetDataLine TARGET_DATA_LINE;
SoundListener(SoundMeter soundMeter, Mixer mixer, AudioFormat audioFormat) throws LineUnavailableException {
SOUNDMETER = soundMeter;
AUDIO_FORMAT = audioFormat;
BUFFER_SIZE = (int) ((AUDIO_FORMAT.getSampleRate() * AUDIO_FORMAT.getSampleSizeInBits()) / REFRESH_RATE);
IS_24_BITS = AUDIO_FORMAT.getSampleSizeInBits() == 24;
TARGET_DATA_LINE = AudioSystem.getTargetDataLine(AUDIO_FORMAT, mixer.getMixerInfo());
TARGET_DATA_LINE.open(AUDIO_FORMAT);
TARGET_DATA_LINE.start();
setName("SoundListener");
setDaemon(true);
start();
}
@Override
public void run() {
System.out.println("Thread " + getName() + " started!");
while (!isInterrupted()) {
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = TARGET_DATA_LINE.read(buffer, 0, BUFFER_SIZE);
if (bytesRead >= 0) {
int max = 0;
for (int i = 0; i < bytesRead; ) {
byte[] subBuffer = new byte[3];
subBuffer[0] = buffer[i++];
subBuffer[1] = buffer[i++];
if (IS_24_BITS) {
subBuffer[2] = buffer[i++];
}
int currentValue = 0;
if (AUDIO_FORMAT.isBigEndian()) {
if (IS_24_BITS) {
currentValue += subBuffer[0] << 16;
currentValue += subBuffer[1] << 8;
currentValue += subBuffer[2];
} else {
currentValue += subBuffer[0] << 8;
currentValue += subBuffer[1];
}
} else {
if (IS_24_BITS) {
currentValue += subBuffer[2] << 16;
}
currentValue += subBuffer[0];
currentValue += subBuffer[1] << 8;
}
if (currentValue > max) {
max = currentValue;
}
}
SOUNDMETER.setVolume(max);
}
}
TARGET_DATA_LINE.close();
System.out.println("Thread " + getName() + " stopped!");
}
}
它在初始化时启动输入接口,然后立即启动自身。
SoundMeter
类是外部类,它管理混音器使用和初始化Thread以及调用Thread对象上的中断( 编辑 :此类也接收计算的音量值)。
我认为问题是阻塞的TargetDataLine.read()
方法,但是我不确定如何解决此问题。
在这种情况下,我不使用中断API,而是使用一个boolean
标志isRunning
,并在线程停止时将其设置为false
。
我们可能无法观察到interrupt()
设置的标志,尤其是在线程阻塞时:
如果在调用
Object
类的wait()
,wait(long)
或wait(long, int)
方法或join()
,join(long)
,join(long, int)
方法时阻塞了此线程,此类的sleep(long)
或sleep(long, int)
方法,则其中断状态将被清除,并将收到InterruptedException
。
由于TargetDataLine.read
说它可能会阻塞,所以没有理由期望isInterrupted()
在这里可以工作。
如果TargetDataLine
收到InterruptedException
时再次中断自身以为我们设置标志,那将是很好的选择,但是没有什么要说的。
Thread.interrupt()以常用方式设置标志,仅此而已
如果上述条件均不成立,则将设置该线程的中断状态。
因此,在调用Thread.interrupt()之后,线程将在(!isInterrupted())的第一次检查期间结束
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.