Je lisais environ CopyOnWriteArrayList
et je me demandais comment je peux démontrer la course de données dans la classe ArrayList
. Fondamentalement, j'essaie de simuler une situation où ArrayList
échoue de sorte qu'il devient nécessaire d'utiliser CopyOnWriteArrayList
. Toutes les suggestions sur la façon de simuler cela.Course de données dans la classe Java ArrayList
Répondre
Une course est lorsque deux (ou plus) threads essaient de fonctionner sur des données partagées, et la sortie finale dépend de l'ordre des données est accessible (et cet ordre est indéterministe)
de Wikipédia:
Une condition de course ou un risque de course est une faille dans un système ou un processus électronique où la sortie et/ou le résultat du processus dépend de façon inattendue et critique de la séquence ou du moment des autres événements. Le terme provient de l'idée de deux signaux qui se courent l'un l'autre pour influencer la sortie en premier.
Par exemple:
public class Test {
private static List<String> list = new CopyOnWriteArrayList<String>();
public static void main(String[] args) throws Exception {
ExecutorService e = Executors.newFixedThreadPool(5);
e.execute(new WriterTask());
e.execute(new WriterTask());
e.execute(new WriterTask());
e.execute(new WriterTask());
e.execute(new WriterTask());
e.awaitTermination(20, TimeUnit.SECONDS);
}
static class WriterTask implements Runnable {
@Override
public void run() {
for (int i = 0; i < 25000; i ++) {
list.add("a");
}
}
}
}
Ceci, cependant, échoue lors de l'utilisation ArrayList
, avec ArrayIndexOutOfbounds
. En effet, avant l'insertion, le ensureCapacity(..)
doit être appelé pour s'assurer que le tableau interne peut contenir les nouvelles données. Et voici ce qui se passe:
- le premier thread appelle
add(..)
, qui appelle à son tourensureCapacity(currentSize + 1)
- avant le premier fil est en fait incrémentée la taille, le 2ème thread appelle également
ensureCapacity(currentSize + 1)
. - parce que les deux ont lu la valeur initiale de
currentSize
, la nouvelle taille du tableau interne estcurrentSize + 1
- les deux fils faire l'opération coûteuse pour copier le vieux tableau dans une étendue, avec la nouvelle taille (qui ne peut pas tenir les deux ajouts)
- Ensuite, chacun d'eux tente d'affecter le nouvel élément à
array[size++]
. Le premier réussit, le second échoue, car le tableau interne n'a pas été étendu correctement, en raison de la condition de réception.
Cela se produit parce que deux fils ont essayé d'ajouter des éléments en même temps sur la même structure, et l'ajout d'un d'entre eux a surchargé l'ajout de l'autre (la première a été perdue)
un autre avantage de CopyOnWriteArrayList
- plusieurs threads écrire dans le
ArrayList
- un fil parcourt le
ArrayList
.Il va sûrement seConcurrentModificationException
Voici comment le démontrer:
public class Test {
private static List<String> list = new ArrayList<String>();
public static void main(String[] args) throws Exception {
ExecutorService e = Executors.newFixedThreadPool(2);
e.execute(new WriterTask());
e.execute(new ReaderTask());
}
static class ReaderTask implements Runnable {
@Override
public void run() {
while (true) {
for (String s : list) {
System.out.println(s);
}
}
}
}
static class WriterTask implements Runnable {
@Override
public void run() {
while(true) {
list.add("a");
}
}
}
}
Si vous exécutez ce programme plusieurs fois, vous serez souvent obtiendrais ConcurrentModificationException
avant vous OutOfMemoryError
.
Si vous remplacez par CopyOnWriteArrayList
, vous ne recevez pas l'exception (mais le programme est très lent)
Notez que ceci est juste une démonstration - le bénéfice de CopyOnWriteArrayList
est lorsque le nombre de lectures considérablement numéros le nombre d'écritures.
Deux threads, l'un incrémentant l'arraylist et l'autre décrémentant. La course de données pourrait arriver ici.
Exemple:
for (int i = 0; i < array.size(); ++i) {
Element elm = array.get(i);
doSomethingWith(elm);
}
Si un autre thread appelle array.clear() avant ce appels fil array.get (i), mais après i est comparé à array.size(), -> ArrayIndexOutOfBoundsException.
- 1. Problème avec la classe ArrayList en Java
- 2. chercher dans java ArrayList
- 3. StringCollection ou ArrayList dans la classe
- 4. Problèmes de Java avec ArrayList
- 5. Suppression de ArrayList Java
- 6. Java ArrayList et HashMap sur la volée
- 7. Tableau de ArrayList Java
- 8. Aide de Java ArrayList!
- 9. Java Arraylist Aide
- 10. Quelle est l'inverse de (ArrayList) .toString pour une Java ArrayList?
- 11. Problème avec ArrayList dans Java
- 12. java arraylist format
- 13. Java: comment ArrayList gère la mémoire
- 14. Correct façon de synchroniser ArrayList dans Java
- 15. Java ArrayList: fusionner ArrayLists dans ArrayLists pour créer une ArrayList
- 16. Conditions de course dans les méthodes de classe Ruby
- 17. Java Bean ArrayList
- 18. Java ArrayList Index
- 19. Comparaison de Java ArrayList- TicTacToe
- 20. Ajout d'instances d'une classe à une Arraylist en java
- 21. Java Modcount (ArrayList)
- 22. Comment stocker des valeurs Arraylist dans la base de données dans Java?
- 23. Nom de la classe de variables Java
- 24. vecteur java à arraylist
- 25. Saving ArrayList dans la base de données SQLite dans Android
- 26. Java: ArrayList des tableaux de chaîne
- 27. Java - copier des objets arraylist
- 28. tableau dynamique 2d dans Java utilisant Arraylist
- 29. Java ArrayList recherchant plusieurs chaînes
- 30. Comment comparer deux valeurs Arraylist dans java?
@Mark - mais la question concerne le multithreading, et cette exception (comme son nom l'indique) est intrinsèquement "multithread". – Bozho
On dirait que je n'ai pas tout à fait compris. Pouvez-vous nous dire comment les courses de données sont causées? – devnull
@iJeeves voir mis à jour – Bozho