简体   繁体   English

在InputStream的read()中阻止I / O

[英]Block I/O in InputStream's read()

I'm trying to write an algorithm, that downloads a video live stream. 我正在尝试编写一种算法,可以下载视频直播流。 Specifically, the respective stream I'm trying to fetch is based on a dynamic .m3u8 playlist file, which periodically provides URIs of new video files. 具体来说,我要提取的各个流基于动态.m3u8播放列表文件,该文件会定期提供新视频文件的URI。 The main goal is to combine those individual media files into one coherent InputStream. 主要目标是将这些单独的媒体文件组合到一个一致的InputStream中。
I actually succeeded in getting it to work: I periodically check for new media files, that appear inside the playlist, and pass their HTTP streams to a custom InputStream implementation, namely InputStreamChain . 我实际上成功地使它起作用:我定期检查播放列表中是否出现了新的媒体文件,并将它们的HTTP流传递给自定义的InputStream实现,即InputStreamChain Since it's a live stream, I assume it to be endless , at least for the time being. 由于它是实时流,因此至少在目前,我认为它是无止境的 Ergo, I wanted my InputStreamChain 's read() never to send the -1. 因此,我希望我的InputStreamChainread()永远不要发送-1。 Unfortunately, it did; 不幸的是,它确实做到了。 every time when all queued media streams were consumed, the InputStreamChain ended. 每当所有排队的媒体流都用完时, InputStreamChain结束。 Instead, I wanted it to block I/O, until a new media file arrives. 相反,我希望它阻止I / O,直到出现新的媒体文件。 So, I came up with a working solution: I adjusted the read() method to loop until there's a new stream available (a TimerTask will provide the new files). 因此,我想出了一个可行的解决方案:我调整了read()方法使其循环播放,直到有新的流可用为止( TimerTask将提供新文件)。 In the loop, I built in a Thread.sleep() , in order to reduce the CPU load: 在循环中,我内置了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;
}

Although it seems to work, I have a feeling, that I'm not doing it how I'm supposed to. 尽管它似乎可行,但是我有一种感觉,就是我没有按照我的预期去做。 I also tried using Lock together with Condition.await() , but when my TimerTask tried to trigger Condition.signal() , it just threw a IllegalMonitorStateException . 我还尝试将LockCondition.await()一起使用,但是当我的TimerTask尝试触发Condition.signal() ,它只是抛出了IllegalMonitorStateException
That's why I'm asking the question : 这就是为什么我问这个问题

In what way should I delay/block an InputStream's read() method, especially in my scenario? 我应该以哪种方式延迟/阻止InputStream的read()方法,尤其是在我的场景中?

Edit: 编辑:

For the sake of completeness, I'm going to provide my failed Lock approach, too: 为了完整起见,我还将提供失败的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;
}

Probably you are not using synchronized block. 可能您未使用同步块。 Here is an example: 这是一个例子:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM