我試圖編寫一個算法,下載視頻直播流。具體而言,我試圖獲取的相應數據流基於一個動態的播放列表文件,該文件定期提供新視頻文件的URI。主要目標是將這些單獨的媒體文件組合成一個連貫的InputStream。
我確實成功地實現了它的工作:我定期檢查播放列表中出現的新媒體文件,並將它們的HTTP流傳遞給自定義InputStream實現,即InputStreamChain。由於它是一個直播流,我認爲它至少在目前是無盡的。埃爾戈,我想我的InputStreamChain
的read()
永遠不會發送-1。不幸的是,它確實;每當所有排隊的媒體流被消耗時,InputStreamChain
就結束了。相反,我希望它阻止I/O,直到一個新的媒體文件到達。 所以,我想出了一個工作解決方案:我調整了read()
方法以循環,直到有新的可用流(TimerTask
將提供新文件)。在循環中,我建一個Thread.sleep()
,以降低CPU的負荷:InputStream中的塊I/O讀取()
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;
}
您必須獲取鎖定以發出信號並等待條件。 – Flavio
@Flavio我從頭頂寫下了自己的'Lock'方法。我哪裏做錯了? – MCL
你必須在'cond.signal()'之前調用'lock.lock()',然後''lock.unlock()'。 – Flavio