Aangepaste threadpools in Java 8 parallelle streams

1. Overzicht

Java 8 introduceerde het concept van Streams als een efficiënte manier om bulkbewerkingen op gegevens uit te voeren. En parallel Streams kan worden verkregen in omgevingen die gelijktijdigheid ondersteunen.

Deze streams kunnen worden geleverd met verbeterde prestaties - ten koste van overhead van meerdere threads.

In deze korte tutorial zullen we kijken naar een van de grootste beperkingen van Stroom API en kijk hoe je een parallelle stream kunt laten werken met een custom ThreadPool bijvoorbeeld, als alternatief - er is een bibliotheek die dit afhandelt.

2. Parallel Stroom

Laten we beginnen met een eenvoudig voorbeeld: de parallelStream methode op een van de Verzameling types - die een mogelijk parallel Stroom:

@ Test openbare ongeldig gegevenList_whenCallingParallelStream_shouldBeParallelStream () {Lijst aList = nieuwe ArrayList (); Stroom parallelStream = aList.parallelStream (); assertTrue (parallelStream.isParallel ()); }

De standaardverwerking die plaatsvindt in een dergelijke Stroom gebruikt de ForkJoinPool.commonPool (),een Thread Pool gedeeld door de hele applicatie.

3. Aangepast Thread Pool

We kunnen eigenlijk een gewoonte doorgeven ThreadPool bij het verwerken van de stroom.

In het volgende voorbeeld hebben we een parallel Stroom gebruik een gewoonte Thread Pool om de som van lange waarden van 1 tot 1.000.000 te berekenen, inclusief:

@Test openbare ongeldige giveRangeOfLongs_whenSummedInParallel_shouldBeEqualToExpectedTotal () gooit InterruptedException, ExecutionException {long firstNum = 1; long lastNum = 1_000_000; Lijst aList = LongStream.rangeClosed (firstNum, lastNum) .boxed () .collect (Collectors.toList ()); ForkJoinPool customThreadPool = nieuwe ForkJoinPool (4); long actualTotal = customThreadPool.submit (() -> aList.parallelStream (). reduce (0L, Long :: sum)). get (); assertEquals ((lastNum + firstNum) * lastNum / 2, actualTotal); }

We gebruikten de ForkJoinPool constructor met een parallellisme-niveau van 4. Enig experiment is vereist om de optimale waarde voor verschillende omgevingen te bepalen, maar een goede vuistregel is simpelweg het aantal te kiezen op basis van het aantal kernen dat uw CPU heeft.

Vervolgens hebben we de inhoud van de parallel verwerkt Stroom, samenvattend in de verminderen bellen.

Dit eenvoudige voorbeeld toont misschien niet het volledige nut van het gebruik van een gewoonte aan Thread Pool, maar de voordelen worden duidelijk in situaties waarin we het gemeenschappelijke niet willen verbinden Thread Pool met langlopende taken (bijv. het verwerken van gegevens uit een netwerkbron), of de common Thread Pool wordt gebruikt door andere componenten binnen de applicatie.

4. Conclusie

We hebben kort gekeken hoe je een parallel loopt Stroom met behulp van een gewoonte Thread Pool. In de juiste omgeving en met het juiste gebruik van het parallellisme-niveau kan in bepaalde situaties prestatieverbeteringen worden behaald.

De volledige codevoorbeelden waarnaar in dit artikel wordt verwezen, zijn te vinden op Github.