[英]Block I/O in InputStream's read()
我正在尝试编写一种算法,可以下载视频直播流。 具体来说,我要提取的各个流基于动态.m3u8播放列表文件,该文件会定期提供新视频文件的URI。 主要目标是将这些单独的媒体文件组合到一个一致的InputStream中。
我实际上成功地使它起作用:我定期检查播放列表中是否出现了新的媒体文件,并将它们的HTTP流传递给自定义的InputStream实现,即InputStreamChain 。 由于它是实时流,因此至少在目前,我认为它是无止境的 。 因此,我希望我的InputStreamChain
的read()
永远不要发送-1。 不幸的是,它确实做到了。 每当所有排队的媒体流都用完时, InputStreamChain
结束。 相反,我希望它阻止I / O,直到出现新的媒体文件。 因此,我想出了一个可行的解决方案:我调整了read()
方法使其循环播放,直到有新的流可用为止( TimerTask
将提供新文件)。 在循环中,我内置了Thread.sleep()
,以减少CPU负载:
public int read() throws IOException {
int bit = current.read();
if (bit == -1 && streams.size() > 0) {
// left out due to lacking relevance
} else if(bit == -1 && streams.size() == 0) {
while(streams.size() == 0) {
Thread.currentThread().sleep(50);
}
return read();
}
return bit;
}
尽管它似乎可行,但是我有一种感觉,就是我没有按照我的预期去做。 我还尝试将Lock
与Condition.await()
一起使用,但是当我的TimerTask
尝试触发Condition.signal()
,它只是抛出了IllegalMonitorStateException
。
这就是为什么我问这个问题 :
我应该以哪种方式延迟/阻止InputStream的read()
方法,尤其是在我的场景中?
编辑:
为了完整起见,我还将提供失败的Lock
方法:
private ReentrantLock ioLock;
private Condition ioCond;
private boolean waitingForStream = false;
public InputStreamChain() {
ioLock = new ReentrantLock();
ioCond = ioLock.newCondition();
}
public synchronized InputStreamChain addInputStream(final InputStream stream) {
streams.addLast(stream);
if (current == null) {
current = streams.removeFirst();
}
if(waitingForStream) {
ioCond.signal();
}
return this;
}
public int read() throws IOException {
int bit = current.read();
if (bit == -1 && streams.size() > 0) {
// do stuff
} else if(bit == -1) {
waitingForStream = true;
ioLock.lock();
try {
ioCond.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
waitingForStream = false;
ioLock.unlock();
}
return read();
}
return bit;
}
可能您未使用同步块。 这是一个例子:
class MyReader
{
public int read() throws IOException {
int bit = current.read();
if (bit == -1 && streams.size() > 0) {
// left out due to lacking relevance
} else if(bit == -1 && streams.size() == 0) {
waitForNextStream();
return read();
}
return bit;
}
private synchronized void waitForNextStream()
{
// TODO add close handling, set current here
while (streams.isEmpty())
{
wait();
}
}
public synchronized void addNextStream(InputStream is)
{
streams.add(is);
notify();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.