2015-06-12 19 views
28

In JDK8, quanti thread vengono generati quando utilizzo parallelStream? Ad esempio, nel codice:Quanti thread vengono generati in parallelStream in Java 8?

list.parallelStream().forEach(/** Do Something */); 

Se questo elenco contiene 100000 elementi, quanti thread verranno generati?

Inoltre, ogni thread ottiene lo stesso numero di elementi su cui lavorare o è assegnato casualmente?

+4

Hai letto cosa dice la documentazione? – Kayaman

+5

http://stackoverflow.com/questions/21163108/custom-thread-pool-in-java-8-parallel-stream/21172732#21172732 – assylias

+0

@assylias Davvero una buona risposta. –

risposta

28

L'implementazione Oracle [1] del flusso parallelo utilizza il thread corrente e in aggiunta a quello, se necessario, anche i thread che compongono il pool predefinito di fork fork ForkJoinPool.common(), che ha una dimensione predefinita uguale a uno in meno del numero dei core della tua CPU.

Quella dimensione predefinita del pool comune può essere modificato con questa proprietà:

-Djava.util.concurrent.ForkJoinPool.common.parallelism=8 

In alternativa, è possibile utilizzare la propria piscina:

ForkJoinPool myPool = new ForkJoinPool(8); 
myPool.submit(() -> 
    list.parallelStream().forEach(/* Do Something */); 
).get(); 

Per quanto riguarda l'ordine, i lavori saranno eseguiti come appena un thread è disponibile, in nessun ordine specifico.

[1] Come correttamente sottolineato da @Holger questo è un dettaglio specifico dell'implementazione (con solo one vague reference nella parte inferiore di un documento), entrambi gli approcci funzioneranno su JVM di Oracle ma non è sicuramente garantito il funzionamento su JVM da altri i fornitori, la proprietà non potrebbe esistere in un'implementazione non Oracle e gli Stream non potrebbero nemmeno utilizzare uno ForkJoinPool internamente rendendo l'alternativa basata sul comportamento di ForkJoinTask.fork completamente inutile (see here per i dettagli su questo).

+2

Forse vale la pena aggiungere che se il numero di attività è abbastanza piccolo, il flusso parallelo potrebbe effettivamente essere eseguito nel thread principale. – assylias

+0

@assylias corretto. –

+6

Va notato che l'uso dell'API 'Stream' di' ForkJoinPool' è un dettaglio di implementazione. Pertanto, entrambe le soluzioni funzionano con l'attuale implementazione di Oracle, ma non sono garantite per funzionare ovunque. – Holger

2

Mentre @uraimo è corretto, la risposta dipende esattamente da cosa "Fa qualcosa". L'API parallel.streams utilizza la classe CountedCompleter che presenta alcuni problemi interessanti. Dal momento che il framework F/J non usa un oggetto separato per contenere i risultati, lunghe catene potrebbero risultare in un OOME. Anche quelle lunghe catene possono a volte causare uno Stack Overflow. La risposta a questi problemi è l'uso della tecnica Paraquential come ho sottolineato in this article.

L'altro problema è la creazione eccessiva di thread quando si utilizza il parallelo parallelo perOgni.

Problemi correlati