如何使用队列提供无限流?

时间:2015-04-22 21:46:16

标签: java java-8 java-stream

我想要几个threads来读取文件。这些文件是包含多个文本文件的ZIP个文件。因此必须逐行读取每个文件。

应将文件的任何内容发送到某种queue。队列本身应该从工作线程无限处理。

如果可能的话,如何实施这样的场景? 我提出了一些伪代码,但我真的不知道如何实现它:

Queue<String> queue;

//multiple threads:
BufferedReader br;
queue.add(br.readLine());

//processing thread for the queue:
queue.stream().parallel().forEach(line -> convertAndWrite(line));

//worker function:
private void convertAndWrite(String line) {
    //convert the line to an output format,
    //and write each line eg to an output file or perist in DB, whatever
}

3 个答案:

答案 0 :(得分:1)

看一下How to interconect non-paralel stream with parallel stream(one producer multiple consumers)的答案。对于此问题,使用无法并行化的流填充阻塞队列。实现了可并行化的分裂器,耗尽了这个队列。如果您希望文件是连续的,那么您可能只有一个读取器可以填充队列。

然后使用StreamSupport从分裂器创建流。阻塞队列支持并发修改,因此spliterator实现可以并行化,因此您的流可以并行化。如果您的下游编写器是可并行化的,那么您的整个消费者端都可以并行化。

如果您的读者遇到异常,则将End-of-Stream标记(可能作为final子句的一部分)推入BlockingQueue并重新抛出。只有一个tryAdvance调用者(参见AbstractSpliterator),因此单个End-of-Stream标记足以终止所有并行流。

答案 1 :(得分:0)

如果您使用 LinkedList LinkedBlockingQueue而不是Queue(虽然技术上是 LinkedList LinkedBlockingQueue实现),但是这里有一些ya伪代码队列):

while (true) {
    if (!(queue.isEmpty())) {
        try {
            TheTypeOfElementsInQueue element = queue.removeFirst();
            // do something with element
        } catch (NoSuchElementException e) {
            // just in case!
        }
    }
}

我把它放到实现runnable的类的run()中,并从中创建了一个线程。我这样做的方式是使用LinkedList,但由于LinkedLists不是线程安全的,所以也许LinkedBlockingQueue会更好。

答案 2 :(得分:0)

要实现监视文件夹以查找新文件外观的任务,我将使用Java WatchService和流this article

通过WatchService注册文件夹更新:

Path path = Paths.get(".");
WatchService watchService =  path.getFileSystem().newWatchService();
path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);

获取文件夹更新并通过流处理它们:

WatchKey watchKey = null;
while (true) {
    watchKey = watchService.poll(10, TimeUnit.MINUTES);
    if(watchKey != null) {
        watchKey.pollEvents().stream().forEach(event -> System.out.println(event.context()));
    }
    watchKey.reset();
}

在第

watchKey.pollEvents().stream().forEach(event -> System.out.println(event.context()));

我想你可以使用并行流,event.context()这里是一个Path实例,用于新创建的文件。因此,您可以通过其他流操作(如map等)继续处理其内容。