中断并行流执行

时间:2014-06-16 12:18:26

标签: multithreading concurrency java-8 java-stream

考虑以下代码:

Thread thread = new Thread(() -> tasks.parallelStream().forEach(Runnable::run));

任务是应该并行执行的Runnable列表。 当我们启动这个线程并开始执行时,根据一些计算,我们需要中断(取消)所有这些任务。

中断线程只会停止其中一个执行。我们如何处理他人?或者Streams不应该那样使用?或者你知道更好的解决方案吗?

3 个答案:

答案 0 :(得分:3)

您实际上并未在要创建的线程上运行Runnables。您正在运行将提交到池的线程,因此:

Thread thread = new Thread(() -> tasks.parallelStream().forEach(Runnable::run));

在这个例子中,你做的是较小的术语

List<Runnable> tasks = ...;
Thread thread = new Thread(new Runnable(){
    public void run(){
       for(Runnable r : tasks){
          ForkJoinPool.commonPool().submit(r);
       }
    }
});

这是因为您在处理并行执行时使用了委托给公共池的parallelStream

据我所知,你无法使用parallelStream来处理正在执行任务的线程,所以可能运气不好。你总是可以做一些棘手的事情来获得这个线程,但这可能不是最好的主意。

答案 1 :(得分:2)

类似以下的内容应该适合您:

AtomicBoolean shouldCancel = new AtomicBoolean();
...
tasks.parallelStream().allMatch(task->{
    task.run();
    return !shouldCancel.get();
});

方法allMatch的文档特别指出,“如果不需要确定结果,则可能不对所有元素评估谓词。”因此,如果要取消的谓词不匹配,则无需再进行求值。此外,您可以检查返回结果以查看循环是否已取消。

答案 2 :(得分:1)

您可以使用ForkJoinPool来中断线程:

@Test
public void testInterruptParallelStream() throws Exception {
    final AtomicReference<InterruptedException> exc = new AtomicReference<>();

    final ForkJoinPool forkJoinPool = new ForkJoinPool(4);
    // use the pool with a parallel stream to execute some tasks
    forkJoinPool.submit(() -> {
        Stream.generate(Object::new).parallel().forEach(obj -> {
            synchronized (obj) {
                try {
                    // task that is blocking
                    obj.wait();
                } catch (final InterruptedException e) {
                    exc.set(e);
                }
            }
        });
    });

    // wait until the stream got started
    Threads.sleep(500);
    // now we want to interrupt the task execution
    forkJoinPool.shutdownNow();
    // wait for the interrupt to occur
    Threads.sleep(500);
    // check that we really got an interruption in the parallel stream threads
    assertTrue(exc.get() instanceof InterruptedException);
}

工作线程确实被中断,终止阻塞操作。您也可以在shutdown()内致电Consumer

请注意,这些睡眠可能不会针对正确的单元测试进行调整,您可能有更好的想法,只需等待即可。但它足以表明它正在发挥作用。