Skip to content

Commit

Permalink
feat(streams): 馃幐 parallel streams, translated
Browse files Browse the repository at this point in the history
Refers: #7
  • Loading branch information
rcmoutinho committed Sep 12, 2019
1 parent de27189 commit d52a7c4
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 67 deletions.
90 changes: 44 additions & 46 deletions book/05-java-streams/sections/02-parallel-streams.asc
Original file line number Diff line number Diff line change
@@ -1,208 +1,206 @@
:java-package: src/org/j6toj8/streams
:section-java-package: ../../../{java-package}

=== Streams Paralelos
=== Parallel Streams

.Objetivo
.Objective
--------------------------------------------------
Develop code that uses parallel streams, including decomposition operation and reduction operation in streams
-
Desenvolver c贸digo que usa Streams Paralelos, incluindo opera莽茫o de decomposi莽茫o e opera莽茫o de redu莽茫o em Streams
--------------------------------------------------

_Streams_ podem ser sequenciais ou paralelos. Os sequencias foram vistos na se莽茫o anterior, enquanto os paralelos ser茫o apresentados nesta se莽茫o. _Streams_ paralelos s茫o executados por mais de uma _Thread_, geralmente uma quantidade igual 脿 quantidade de n煤cleos do processador onde a aplica莽茫o est谩 sendo executada. Apesar disso, nem sempre 茅 煤til utiliz谩-los. Seu ganho real 茅 em _Streams_ com grande volumes de dados. Em um _Stream_ pequeno, transform谩-lo em paralelo pode at茅 causar uma perda de performance.
_Streams_ can be sequential or parallel. Sequential was seen in the previous section, while parallels will be presented in this section. Parallel _Streams_ are executed by more than one _Thread_, usually equal to the number of processor cores where the application is running. Nevertheless, it is not always useful to use them. Your actual gain is _Streams_ using large volumes of data. In a small _Stream_, turning it parallel can even cause a loss of performance.

Ao utilizar qualquer tipo de _Stream_, 茅 recomend谩vel n茫o executar fun莽玫es lambdas que causem efeitos colaterais, como mudan莽as no estado de objetos. Em _Streams_ paralelos essa recomenda莽茫o 茅 ainda mais importante.
When using any kind _Stream_, it is recommended not to perform Lambda functions that cause side effects, such as changes in the state of objects. In parallel _Streams_, this recommendation is even more important.

. 脡 poss铆vel transformar qualquer _Stream_ em paralelo utilizando o m茅todo `parallel`.
. You can make any _Stream_ parallel using the `parallel` method.
+
[source,java,indent=0]
.{java-package}/parallelstreams/Streams_Parallel.java
----
include::{section-java-package}/parallelstreams/Streams_Parallel.java[tag=code]
----

. 脡 poss铆vel criar _Streams_ paralelos diretamente em Cole莽玫es atrav茅s do m茅todo `parallelStream`.
. You can create parallel _Streams_ directly in Collections through the `parallelStream` method.
+
[source,java,indent=0]
.{java-package}/parallelstreams/Streams_ParallelStream.java
----
include::{section-java-package}/parallelstreams/Streams_ParallelStream.java[tag=code]
----

. Ao utilizar a opera莽茫o `forEach` em um _Stream_ paralelo, a ordem de execu莽茫o n茫o 茅 garantida.
. When using the `forEach` operation on a parallel _Stream_, the order of execution is not guaranteed.
+
[source,java,indent=0]
.{java-package}/parallelstreams/Streams_ParallelForEach.java
----
include::{section-java-package}/parallelstreams/Streams_ParallelForEach.java[tag=code]
----
+
.Sa铆da no console
.console output
[source,console]
----
Sequencial:
Sequential:
A
B
C
Paralelo:
Parallel:
B
C
A
----
+
O _Stream_ paralelo poderia ter impresso em qualquer ordem, pois n茫o h谩 nenhuma garantia na ordem em que os elementos ser茫o tratados.
The parallel _Stream_ could have printed in any order as there is no guarantee in the order in which the elements will be handled.

. A opera莽茫o `forEachOrdered` garante que a ordem ser谩 mantida mesmo em _Streams_ paralelos.
. The `forEachOrdered` operation ensures that order will be maintained even in parallel _Streams_.
+
[source,java,indent=0]
.{java-package}/parallelstreams/Streams_ParallelForEachOrdered.java
----
include::{section-java-package}/parallelstreams/Streams_ParallelForEachOrdered.java[tag=code]
----
+
.Sa铆da no console
.console output
[source,console]
----
Sequencial:
Sequential:
A
B
C
Paralelo:
Parallel:
A
B
C
----

. Em cole莽玫es com muitos objetos pode haver um ganho consider谩vel de performance.
. In collections with many objects, there can be a considerable performance gain.
+
[source,java,indent=0]
.{java-package}/parallelstreams/Streams_ParallelPerformance.java
----
include::{section-java-package}/parallelstreams/Streams_ParallelPerformance.java[tag=code]
----
+
.Sa铆da no console
.console output
[source,console]
----
Tempo stream sequencial: 9863
Tempo stream paralelo: 1479
Sequential Stream time: 9863
Parallel Stream time: 1479
----
+
Perceba que na m谩quina onde o c贸digo foi executado, a execu莽茫o em paralelo demorou apenas 15% do tempo da execu莽茫o sequencial. Esse n茫o 茅 um teste minucioso, mas mostra o potencial de _Streams_ paralelos.
Note that on the machine where the code was executed, parallel execution took only 15% of the sequential execution time. This is not a thorough test, but it does show the potential of parallel _Streams_.

. Opera莽玫es intermedi谩rias que alteram o estado de objetos podem gerar resultados inesperados ao serem executadas em paralelo.
. Intermediate operations that change the state of objects can produce unexpected results when executed in parallel.
+
[source,java,indent=0]
.{java-package}/parallelstreams/Streams_ParallelStatefulOperation.java
----
include::{section-java-package}/parallelstreams/Streams_ParallelStatefulOperation.java[tag=code]
----
+
.Sa铆da no console
.console output
[source,console]
----
Ordem no forEachOrdered:
Order on forEachOrdered:
A
B
C
Ordem na synchronizedList:
Order on synchronizedList:
A
C
B
----
+
Perceba que a ordem foi respeitada na 煤ltima opera莽茫o do _Stream_, o `forEachOrdered`, mas n茫o foi respeitada na execu莽茫o da opera莽茫o intermedi谩ria `map`. Isso ocorre porque essa opera莽茫o intermedi谩ria n茫o precisa seguir a ordem dos itens do stream.
Note that the order was respected in the last _Stream_ operation, `forEachOrdered`, but was not respected when performing the `map` intermediate operation. This is because this intermediate operation does not have to follow the order of stream items.

. Diferente da execu莽茫o em um _Stream_ sequencial, a opera莽茫o `findAny` traz resultados realmente aleat贸rios ao ser executada em um _Stream_ paralelo.
. Unlike running in a sequential _Stream_, the `findAny` operation brings really random results when executed in a parallel _Stream_.
+
[source,java,indent=0]
.{java-package}/parallelstreams/Streams_ParallelFindAny.java
----
include::{section-java-package}/parallelstreams/Streams_ParallelFindAny.java[tag=code]
----
+
.Sa铆da no console
.console output
[source,console]
----
findAny Sequencial: 7
findAny Paralelo: 9
findAny Sequential: 7
findAny Parallel: 9
----

. Ao realizar uma opera莽茫o de reduce n茫o h谩 problema caso o acumulador seja associativo.
. When performing a reduce operation there is no problem if the accumulator is associative.
+
[source,java,indent=0]
.{java-package}/parallelstreams/Streams_ParallelReduceAssociative.java
----
include::{section-java-package}/parallelstreams/Streams_ParallelReduceAssociative.java[tag=code]
----
+
.Sa铆da no console
.console output
[source,console]
----
13440
13440
----
+
Perceba que o resultado com o Stream sequencial 茅 id锚ntico ao paralelo. Isso ocorre porque a opera莽茫o de multiplica莽茫o 茅 associativa, ou seja, fazer `(2 x 2) x (3 x 3)` 茅 o mesmo que fazer `(2 x 2 x 3) x 3`, ou at茅 mesmo `2 x (2 x 3) x 3`.
Note that the result with sequential Stream is identical to parallel. This is because the multiplication operation is associative, i.e., doing `(2 x 2) x (3 x 3)` is the same as doing `(2 x 2 x 3) x 3`, or even `2 x (2x3) x3`.

. Ao realizar uma opera莽茫o de reduce acumuladores n茫o-associativos ir谩 gerar resultados inesperados.
. Performing a reduce non-associative accumulator operation will produce unexpected results.
+
[source,java,indent=0]
.{java-package}/parallelstreams/Streams_ParallelReduceNonAssociative.java
----
include::{section-java-package}/parallelstreams/Streams_ParallelReduceNonAssociative.java[tag=code]
----
+
.Sa铆da no console
.console output
[source,console]
----
-18
8
----
+
Isso ocorre pois a opera莽茫o de subtra莽茫o n茫o 茅 associativa, ent茫o o resultado pode variar conforme o _Stream_ for "fatiado" para ser executado em paralelo. Ou seja, fazer `1 - 2 - 3 - 4` n茫o 茅 o mesmo que fazer `(1 - 2) - (3 - 4)`.
This is because the subtraction operation is not associative, so the result may vary as _Stream_ is "sliced" to run in parallel. That is, doing `1 - 2 - 3 - 4` is not the same as doing `(1 - 2) - (3 - 4)`.

. Para coletar o resultado de um _Stream_ paralelo em um mapa, utilize a opera莽茫o `toConcurrentMap`.
. To collect the result of a parallel _Stream_ on a map, use the `toConcurrentMap` operation.
+
[source,java,indent=0]
.{java-package}/parallelstreams/Streams_ParallelToConcurrentMap.java
----
include::{section-java-package}/parallelstreams/Streams_ParallelToConcurrentMap.java[tag=code]
----
+
.Sa铆da no console
.console output
[source,console]
----
toMap: {Roseany=7, Am茅lia=6, Rodrigo=7, Rinaldo=7, Luiz=4}
toConcurrentMap: {Am茅lia=6, Roseany=7, Rodrigo=7, Rinaldo=7, Luiz=4}
----
+
Perceba que o resultados das opera莽玫es pode ser diferente. Ao utilizar o _Collector_ `toConcurrentMap` em um _Stream_ paralelo, as opera莽玫es podem ser executadas em qualquer ordem e n茫o h谩 necessidade de criar m煤ltiplos `Map's` para serem combinados posteriormente. Em grandes _Streams_, isso pode ocasionar em um ganho de performance.
Note that the results of operations may differ. By using _Collector_ `toConcurrentMap` in a parallel _Stream_, operations can be performed in any order and there is no need to create multiple `Map's` to be combined later. In large _Streams_, this can lead to a performance gain.

. Para coletar o resultado de um Stream paralelo utilize _groupingByConcurrent_ ao inv茅s de _groupingBy_.
. To collect the result of a parallel stream use _groupingByConcurrent_ instead of _groupingBy_.
+
[source,java,indent=0]
.{java-package}/parallelstreams/Streams_ParallelGroupingByConcurrent.java
----
include::{section-java-package}/parallelstreams/Streams_ParallelGroupingByConcurrent.java[tag=code]
----
+
.Sa铆da no console
.console output
[source,console]
----
{4=[Luiz], 6=[Am茅lia], 7=[Rinaldo, Rodrigo, Roseany]}
{4=[Luiz], 6=[Am茅lia], 7=[Roseany, Rodrigo, Rinaldo]}
----
+
Pelo mesmo motivo do exemplo anterior, a ordem pode variar ao utilizar o `groupingByConcurrent`, por茅m pode haver ganho de performance em grandes _Streams_ paralelos, pois a ordem n茫o 茅 necessariamente seguida e n茫o h谩 necessidade de criar m煤ltiplos mapas.
For the same reason as in the previous example, the order may vary when using `groupingByConcurrent`, but there may be performance gains on large parallel _Streams_ as the order is not necessarily followed and there is no need to create multiple maps.

.Refer锚ncias
.References
****
* Working with Parallel Streams
+
Boyarsky, Jeanne; Selikoff, Scott. OCP: Oracle Certified Professional Java SE 8 Programmer II Study Guide (p. 366). Wiley. Edi莽茫o do Kindle.
Boyarsky, Jeanne; Selikoff, Scott. OCP: Oracle Certified Professional Java SE 8 Programmer II Study Guide (p. 366). Wiley. Kindle Edition.
* https://www.baeldung.com/java-8-streams[The Java 8 Stream API Tutorial.]
Expand All @@ -212,4 +210,4 @@ Boyarsky, Jeanne; Selikoff, Scott. OCP: Oracle Certified Professional Java SE 8
* https://docs.oracle.com/javase/8/docs/api/?java/util/stream/Stream.html[Interface Stream<T>.] Java Plataform SE 8.
****
****
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public static void main(String[] args) {
// tag::code[]
String[] array = new String[] { "A", "B", "C" };
Arrays.stream(array)
.parallel() // stream transformado em paralelo
.parallel() // stream transformed in parallel
.forEach(System.out::println);
// end::code[]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ public static void main(String[] args) {
// tag::code[]
Optional<Integer> findAny1 = Stream.of(7, 2, 1, 8, 4, 9, 2, 8)
.findFirst();
System.out.println("findAny Sequencial: " + findAny1.get());
System.out.println("findAny Sequential: " + findAny1.get());

Optional<Integer> findAny2 = Stream.of(7, 2, 1, 8, 4, 9, 2, 8)
.parallel()
.findAny();
System.out.println("findAny Paralelo: " + findAny2.get());
System.out.println("findAny Parallel: " + findAny2.get());
// end::code[]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ public static void main(String[] args) {
// tag::code[]
List<String> list = Arrays.asList("A", "B", "C");

System.out.println("Sequencial: ");
list.stream() // cria um Stream sequencial
System.out.println("Sequential: ");
list.stream() // create a sequential stream
.forEach(System.out::println);

System.out.println("Paralelo: ");
list.parallelStream() // cria um Stream paralelo
System.out.println("Parallel: ");
list.parallelStream() // create a parallel stream
.forEach(System.out::println);
// end::code[]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ public static void main(String[] args) {
// tag::code[]
List<String> list = Arrays.asList("A", "B", "C");

System.out.println("Sequencial: ");
list.stream() // cria um Stream sequencial
System.out.println("Sequential: ");
list.stream() // create a sequential stream
.forEachOrdered(System.out::println);

System.out.println("Paralelo: ");
list.parallelStream() // cria um Stream paralelo
System.out.println("Parallel: ");
list.parallelStream() // create a parallel stream
.forEachOrdered(System.out::println);
// end::code[]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ public class Streams_ParallelPerformance {

public static void main(String[] args) {
// tag::code[]
long inicio = System.currentTimeMillis();
IntStream.range(0, Integer.MAX_VALUE) // stream sequencial
long start = System.currentTimeMillis();
IntStream.range(0, Integer.MAX_VALUE) // sequential stream
.mapToDouble(n -> Math.pow(n, 2))
.average()
.ifPresent(n -> System.out.println("Tempo stream sequencial: " + (System.currentTimeMillis() - inicio)));
.ifPresent(n -> System.out.println("Sequential Stream time: " + (System.currentTimeMillis() - start)));

long inicio2 = System.currentTimeMillis();
long start2 = System.currentTimeMillis();
IntStream.range(0, Integer.MAX_VALUE)
.parallel() // stream paralelo
.parallel() // parallel stream
.mapToDouble(n -> Math.pow(n, 2))
.average()
.ifPresent(n -> System.out.println("Tempo stream paralelo: " + (System.currentTimeMillis() - inicio2)));
.ifPresent(n -> System.out.println("Parallel Stream time: " + (System.currentTimeMillis() - start2)));
// end::code[]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ public static void main(String[] args) {
List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>());
List<String> list = Arrays.asList("A", "B", "C");

System.out.println("Ordem no forEachOrdered: ");
System.out.println("Order on forEachOrdered: ");
list.parallelStream()
.map(s -> {synchronizedList.add(s); return s;}) // opera莽茫o com efeito colateral - altera o estado de um objeto
.map(s -> {synchronizedList.add(s); return s;}) // side effect operation - changes the state of an object
.forEachOrdered(System.out::println);

System.out.println("Ordem na synchronizedList: ");
System.out.println("Order on synchronizedList: ");
for (String s : synchronizedList) {
System.out.println(s);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class Streams_ParallelStream {
public static void main(String[] args) {
// tag::code[]
List<String> list = Arrays.asList("A", "B", "C");
list.parallelStream() // cria um Stream paralelo diretamente
list.parallelStream() // create a parallel stream directly
.forEach(System.out::println);
// end::code[]
}
Expand Down

0 comments on commit d52a7c4

Please sign in to comment.