La spécification garantit-elle que les opérations sur les stream Java séquentiels doivent restr dans le thread actuel?

La spécification garantit-elle que toutes les opérations sur les stream Java séquentiels sont exécutées dans le thread actuel? (Sauf “forEach” et “forEachOrdered”)

Je demande explicitement la spécification, pas ce que l’implémentation actuelle fait. Je peux examiner la mise en œuvre actuelle moi-même et je n’ai pas besoin de vous déranger avec cela. Mais l’implémentation peut changer et il y a d’autres implémentations.

Je demande à cause de ThreadLocals: J’utilise un framework qui utilise ThreadLocals en interne. Même un simple appel tel que company.getName () utilise finalement un ThreadLocal. Je ne peux pas changer la façon dont ce cadre est conçu. Du moins pas dans un délai raisonnable.

Le cahier des charges semble déroutant ici. La documentation du paquet “java.util.stream” indique:

Si les parameters comportementaux ont des effets secondaires, sauf indication contraire explicite, il n’ya aucune garantie quant à la visibilité de ces effets secondaires sur d’autres processus, ni aucune garantie que des opérations différentes sur le “même” élément dans le même pipeline de stream sont exécutés dans le même fil .

Même lorsqu’un pipeline est contraint de produire un résultat cohérent avec l’ordre de recherche des sources du stream (par exemple, IntStream.range (0,5) .parallel (). Map (x -> x * 2) .toArray ( ) doit produire [0, 2, 4, 6, 8]), il n’ya aucune garantie quant à l’ordre dans lequel la fonction de mappage est appliquée à des éléments individuels, ni au fil d’exécution d’un paramètre de comportement exécuté pour un élément donné.

J’interpréterais cela comme suit: chaque opération sur un stream peut avoir lieu dans un thread différent. Mais la documentation de “forEach” et “forEachOrdered” indique explicitement:

Pour n’importe quel élément donné, l’action peut être effectuée à n’importe quel moment et dans n’importe quel thread choisi par la bibliothèque.

Cette déclaration serait redondante si chaque opération de stream pouvait avoir lieu dans un thread non spécifié. Par conséquent, l’inverse est-il vrai: l’exécution de toutes les opérations d’un stream série est garantie dans le thread actuel, à l’exception de “forEach” et “forEachOrdered”?

J’ai cherché sur Google une réponse faisant autorité sur la combinaison de “Java”, “Stream” et “ThreadLocal”, mais je n’ai rien trouvé. Pour conclure, Brian Goetz a répondu à une question connexe sur Stack Overflow, mais il s’agit de l’ordre, pas du fil, et il ne s’agit que de “forEach”, pas des autres méthodes de stream: Est-ce que Stream.forEach respecte la ordre de rencontre des stream séquentiels?

Je pense que la réponse que vous recherchez n’est pas aussi bien définie car elle dépend du consommateur et / ou du séparateur et de leurs caractéristiques:

Avant de lire la citation principale:

https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html#stream

default Stream stream () Renvoie un stream séquentiel avec cette collection comme source. Cette méthode doit être remplacée lorsque la méthode spliterator () ne peut pas renvoyer un séparateur qui est IMMUTABLE, CONCURRENT ou à liaison tardive. (Voir spliterator () pour plus de détails.)

https://docs.oracle.com/javase/8/docs/api/java/util/Spliterator.html#binding

Malgré leur utilité évidente dans les algorithmes parallèles, les séparateurs ne sont pas censés être thread-safe; au lieu de cela, les implémentations d’algorithmes parallèles utilisant des séparateurs devraient garantir que le séparateur n’est utilisé que par un seul thread à la fois. Ceci est généralement facile à atteindre via le confinement de threads en série, ce qui est souvent une conséquence naturelle des algorithmes parallèles classiques qui fonctionnent par décomposition récursive. Un thread appelant trySplit () peut remettre le Spliterator renvoyé à un autre thread, qui peut alors traverser ou fractionner davantage ce Spliterator. Le comportement de fractionnement et de traversée n’est pas défini si deux ou plusieurs threads fonctionnent simultanément sur le même séparateur. Si le thread d’origine transfère un séparateur à un autre thread pour traitement, il est préférable que ce transfert intervienne avant que tous les éléments soient consommés avec tryAdvance (), car certaines garanties (telles que la précision de estimationSize () pour les séparateurs SIZED) ne sont valides. avant le début de la traversée.

Les spliterateurs et les consommateurs ont leurs caractéristiques et définissent la garantie. Supposons que vous opérez dans un streem. Comme les spliterators sont supposés ne pas être thread-safe et manipuler les éléments d’autres spliterators qui pourraient être dans un autre thread, séquentiellement ou non, la garantie est nulle. Cependant, si aucun fractionnement ne survient, les guillemets mèneront à ce qui suit: sous un séparateur, les opérations restront dans le même fil, tout événement menant à un fractionnement rendra l’hypothèse nulle, mais sa valeur sera vraie sinon