Looking for java Answers? Try Ask4KnowledgeBase
Looking for java Keywords? Try Ask4Keywords

Java Language Collections concurrentes


Exemple

Les collections simultanées sont une généralisation des collections thread-safe, ce qui permet une utilisation plus large dans un environnement concurrent.

Bien que les collections thread-safe disposent d'un ajout ou d'une suppression d'éléments sûrs dans plusieurs threads, elles n'ont pas nécessairement une itération sécurisée dans le même contexte (il est possible de ne pas itérer en toute sécurité dans un thread, tandis qu'un autre le modifie en ajoutant / enlever des éléments).

C'est là que les collections concurrentes sont utilisées.

Comme l'itération est souvent l'implémentation de base de plusieurs méthodes en vrac dans des collections, comme addAll , removeAll ou également la copie de collection (via un constructeur ou un autre moyen), le tri ...

Par exemple, le fichier Java SE 5 java.util.concurrent.CopyOnWriteArrayList est une implémentation Lis t sécurisée et simultanée de threads, dont le javadoc stipule:

La méthode d'itérateur de style "instantané" utilise une référence à l'état du tableau au moment où l'itérateur a été créé. Ce tableau ne change jamais pendant la durée de vie de l'itérateur, de sorte que l'interférence est impossible et que l'itérateur est assuré de ne pas lancer l'exception ConcurrentModificationException.

Par conséquent, le code suivant est sécurisé:

public class ThreadSafeAndConcurrent {

public static final List<Integer> LIST = new CopyOnWriteArrayList<>();

public static void main(String[] args) throws InterruptedException {
    Thread modifier = new Thread(new ModifierRunnable());
    Thread iterator = new Thread(new IteratorRunnable());
    modifier.start();
    iterator.start();
    modifier.join();
    iterator.join();
}

public static final class ModifierRunnable implements Runnable {
    @Override
    public void run() {
        try {
            for (int i = 0; i < 50000; i++) {
                LIST.add(i);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public static final class IteratorRunnable implements Runnable {
    @Override
    public void run() {
        try {
            for (int i = 0; i < 10000; i++) {
                long total = 0;
                for(Integer inList : LIST) {
                    total += inList;
                }
                System.out.println(total);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
}

ConcurrentLinkedQueue , qui indique:

Les itérateurs sont faiblement cohérents, renvoyant des éléments reflétant l'état de la file d'attente à un moment donné ou depuis la création de l'itérateur. Ils ne lancent pas java.util.ConcurrentModificationException et peuvent continuer simultanément avec d'autres opérations. Les éléments contenus dans la file d'attente depuis la création de l'itérateur seront renvoyés exactement une fois.

On devrait vérifier les javadocs pour voir si une collection est concurrente ou non. Les attributs de l'itérateur renvoyés par la méthode iterator() ("échec rapide", "peu cohérent", ...) constituent l'attribut le plus important à rechercher.

Thread safe mais exemples non concurrents

Dans le code ci-dessus, changer la déclaration LIST en

public static final List<Integer> LIST = Collections.synchronizedList(new ArrayList<>());

Pourrait (et statistiquement sera sur la plupart des architectures multi-CPU / core modernes) conduire à des exceptions.

Les collections synchronisées à partir des méthodes de l'utilitaire Collections sont sécurisées pour l'ajout / suppression d'éléments, mais pas pour l'itération (à moins que la collection sous-jacente ne lui soit déjà transmise).