I am learning java.util.concurrent package. I reread a bunch of articles, but I just can’t understand the CopyOnWriteArrayList thread-safety principle. More precisely, the principle understood that a duplicate of the collection is being created, and the work is happening to her. But in practice I can not implement it. No decent example found. Here in this article in the example it is clear only that when using CopyOnWriteArrayList when iterating through an iterator, you cannot delete an element. The main question. In which cases we can use CopyOnWriteArrayList thread safety instead of synchronization. I would appreciate any example.
1 answer
ArrayList together with synchronization in some high-loaded application will run slower than CopyOnWriteArrayList, since a regular ArrayList will be blocked by any stream entirely and will be unavailable for other streams. At the same time, CopyOnWriteArrayList does not require blocking by threads, since each thread will work with its own copy of the sheet. When using CopyOnWriteArrayList, when iterating through an iterator, you can delete an item. But this will not affect the enumeration in which the deletion takes place, for example, if you make a conclusion on the screen and delete an item, you will get an output on the screen of the original list entirely. Here is a fairly clear example of how CopyOnWriteArrayList works.
import java.util.List; import java.util.Iterator; import java.util.ArrayList; import java.util.concurrent.CopyOnWriteArrayList; public class CopyOnWriteArrayListExample { List<String> list; public CopyOnWriteArrayListExample() { List<String> lst = new ArrayList<String>(); lst.add("Java"); lst.add("J2EE"); lst.add("J2SE"); lst.add("Collection"); lst.add("Concurrent"); list = new CopyOnWriteArrayList<String>(lst); System.out.println("ЦИКЛ с изменением"); printCollection(true); System.out.println("\nЦИКЛ без изменением"); printCollection(false); } private void printCollection(boolean change) { Iterator<String> iterator = list.iterator(); while(iterator.hasNext()){ String element = iterator.next(); System.out.printf(" %s %n", element); if (change) { if (element.equals("Collection")) { list.add("Новая строка"); list.remove(element); } } } } public static void main(String args[]) { new CopyOnWriteArrayListExample(); System.exit(0); } } At the output you will get the following result:
ЦИКЛ с изменением Java J2EE J2SE Collection Concurrent ЦИКЛ без изменением Java J2EE J2SE Concurrent Новая строка - everything has become much clearer. Thank. Tell me if the following statement is correct: “When iterating through the CopyOnWriteArrayList collection, the work happens as with a normal Arraylist. But when performing modifying operations, an immutable copy of this list is created (cloned). It is in this copy that is continued. Changes are made to the original list. - Maxim Brodsky
- @Maxim Brodsky yes, right, as long as you do not modify CopyOnWriteArrayList, no copies are created. - Vladimir Yarovoy
- I still can not understand. Look at the first answer to this question at stackoverflow.com/questions/28979488/… . There it is written: And that is why we have the CopyOnWriteArrayList "- it makes copy when you write it .. This also avoids the ConcurrentModificationException. Is the change made to the copy of the list? As I understand it is not changeable. - Maxim Brodsky
- @ Maksim Brodsky so what’s wrong?)) Here is the translation: "The add method always creates a copy of the existing array and makes changes to the copy, and then updates the link to the modified array ...". You have understood everything correctly, changes are first made to the copy, and then the reference to the original array begins to refer to the modified one. - Vladimir Yarovoy
- Here we assume the situation. One thread started sorting through this list. At some point, this thread makes an addition. A copy of this list is created right away and changes are already being made in it. But at the same time, another stream wants to add changes to this list and also makes a copy of the original list, since the first one did not have time to make any changes. After that, the first thread makes changes and assigns the original list a link to the modified list. And the second thread makes its own changes and adds a new link to the same list. It turns out the data is overwritten. GESTURE. - Maxim Brodsky