Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 parallelStream findFirst

Suppose we have a list of workers like this :

List<Worker> workers = new ArrayList<>();
workers.add(new Worker(1));
workers.add(new Worker(2));
workers.add(new Worker(3));
workers.add(new Worker(4));
workers.add(new Worker(5));

I want to find the first worker who finished his job, so :

Worker first = workers.parallelStream().filter(Worker::finish).findFirst().orElse(null);

but there's a problem, I don't want to wait for all workers to finish their jobs and then find the first, but the first worker As soon as he finished his job!

public class Test {

    public static void main(String[] args) {
        List<Worker> workers = new ArrayList<>();
        workers.add(new Worker(1));
        workers.add(new Worker(2));
        workers.add(new Worker(3));
        workers.add(new Worker(4));
        workers.add(new Worker(5));
        Worker first = workers.parallelStream().filter(Worker::finish).findFirst().orElse(null);
        if (first != null) {
            System.out.println("id : " + first.id);
        }
    }

    static class Worker {

        int id;

        Worker(int id) {
            this.id = id;
        }

        boolean finish() {
            int t = id * 1000;
            System.out.println(id + " -> " + t);
            try {
                Thread.sleep(t);
            } catch (InterruptedException ignored) {
            }
            return true;
        }

    }

}

is there any way to achieve it using java.util.Stream?

Thanks.

like image 984
FaNaJ Avatar asked Dec 20 '14 05:12

FaNaJ


People also ask

What does findFirst () do in Java?

The findFirst() method finds the first element in a Stream. So, we use this method when we specifically want the first element from a sequence. When there is no encounter order, it returns any element from the Stream. According to the java.

What's the difference between findFirst () and findAny ()?

In Java 8 Stream, the findFirst() returns the first element from a Stream, while findAny() returns any element from a Stream.

Which is faster findAny or findFirst?

Stream findFirst() vs findAny() – ConclusionUse findAny() to get any element from any parallel stream in faster time.

What is ParallelStream in java8?

Java Parallel Streams is a feature of Java 8 and higher, meant for utilizing multiple cores of the processor. Normally any java code has one stream of processing, where it is executed sequentially.


2 Answers

You seem to have a serious misconception about Stream. Streams are not meant to launch workers. In fact, if you use findFirst it may happen that it starts no worker but the first one. And so it also doesn’t wait “for all workers to finish” but only for currently pending threads. But since you have a rather small stream it might be the case that all workers have been started already because there are as much threads available in your environment. But this is not a guaranteed behavior.

Note that if you use a sequential stream instead of a parallel stream it will for sure process the first item only (as it returns true) and none of the other. But since the stream implementation can’t predict that result it will respect you request to “accelerate” the operation via parallel execution and may start processing more items in advance using more threads.

like image 118
Holger Avatar answered Oct 27 '22 01:10

Holger


When you use your finish method as the filter of the Stream, it means that in order to evaluate the filter's predicate for a specific Worker, the Worker has to finish its work.

When you run this code as a parallel Stream, however, it's possible that the filter would be applied on multiple Workers at the same time, in which case, the first one to finish would give you the output. However, you have no control over how many threads the parallel Stream will use. It may decide that some of the Workers should be processed on the same thread, in which case some of them won't be processed at all (since your terminal operation requires that only one Worker finishes its processing).

Therefore, if your goal is that finish is executed for all Workers at the same time, you can't use a Stream (not even a parallel Stream).

like image 45
Eran Avatar answered Oct 27 '22 03:10

Eran