2

1. Set's parallelStream doesn't use enough thread.

Java8 parallelStream doesn't working exactly parallel. In my computer, java8 set's parallelStream is not using enough thread when task's count is smaller than processor's count.

public class ParallelStreamSplitTest {
    @Test
    public void setStreamParallelTest() {
        System.out.printf("Total processor count : %d \n", Runtime.getRuntime().availableProcessors());
        long start = System.currentTimeMillis();
        IntStream.range(1, 8).boxed().collect(Collectors.toCollection(HashSet::new)).parallelStream().forEach((index) -> {
            System.out.println("Starting " + Thread.currentThread().getName() + ",    index=" + index + ", " + new Date());
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
            }
        });
        long end = System.currentTimeMillis();
        System.out.println(Thread.currentThread().getName() + "'s elapsed time : " + (end - start));
    }

    @Test
    public void intStreamParallelTest() {
        System.out.printf("Total processor count : %d \n", Runtime.getRuntime().availableProcessors());
        long start = System.currentTimeMillis();
        IntStream.range(1, 8).parallel().forEach(index -> {
            System.out.println("Starting " + Thread.currentThread().getName() + ",    index=" + index + ", " + new Date());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
        });
        long end = System.currentTimeMillis();
        System.out.println(Thread.currentThread().getName() + "'s elapsed time : " + (end - start));
    }
}

In my code, setStreamParallelTest takes 4 seconds whereas intStreamParallelTest takes 1 second.

I expect that setStreamParallelTest also done in 1 seconds. Is it bug?

2. Is it okay to use parallel stream to call another api in web application? If it is wrong, why?

My web application need to call another api server in parallel. So I use parallel stream to call api.

Sets.newHashSet(api1, api2, api3, api4).parallelStream().forEach(api -> callApiSync(api))

I think all requests bound for my server share a fork-join pool. so, It looks dangerous when one of api's response is slow.

Is it correct?

Community
  • 1
  • 1
  • *"setStreamParallelTest takes 4 seconds"* and *"I expect that setStreamParallelTest also done in 4 seconds"*? Huh?!? If you expect 4 and it takes 4, then what is the problem? – Andreas Apr 12 '19 at 02:33
  • What is `Sets`? --- `HashSet.parallelStream()` does not take any arguments. Did you mean `parallelStream().forEach(api -> callApiSync(api))`? – Andreas Apr 12 '19 at 02:35
  • Using `System.currentTimeMillis()` to do benchmarking is deeply flawed. You cannot make any meaningful conclusions from this kind of benchmarking for many reasons. – scottb Apr 12 '19 at 02:36
  • *FYI:* `new HashSet<>(IntStream.range(1, 8).mapToObj(i -> new Integer(i)).collect(Collectors.toList()))` is better written as `IntStream.range(1, 8).boxed().collect(Collectors.toCollection(HashSet::new))` – Andreas Apr 12 '19 at 02:39
  • @Andreas sorry. is was typo. I expected 1 second. – Freddie yyh Apr 12 '19 at 02:43
  • @Freddieyun So... Fix the question!!! – Andreas Apr 12 '19 at 02:44
  • For #2: Some servers will limit the number of parallel connections it will allow from a single client. Since you don't control how many threads is used, parallel streams might not be the best choice. Using an `ExecutorService` obtained from [`Executors.newFixedThreadPool(int nThreads)`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool-int-) may be a better choice. – Andreas Apr 12 '19 at 02:51
  • @Andreas Thanks for your comments. I edited the question. – Freddie yyh Apr 12 '19 at 04:17
  • Worth reading: the second half of [this answer](https://stackoverflow.com/a/44802784/2711488) – Holger Apr 12 '19 at 09:53

1 Answers1

0

The contract for parallelStream says:

Returns a possibly parallel Stream with this collection as its source. It is allowable for this method to return a sequential stream.

If you want to invoke several tasks in parallel, use an ExecutorService.

Josh
  • 500
  • 3
  • 6
  • But ... be aware that the parallelism of an ExecutorService is limited by the thread pool size. And in practice by the number of cores available to the JVM, time slicing and other things. – Stephen C Apr 12 '19 at 04:55