In single-threaded applications, new ArrayList() is usually used to specify a List collection to store repeatable data.
But under multi-threading, unexpected problems often occur. The code is as follows:
import java.util.*; public class ListTest { public static void main(String[] args) throws InterruptedException { // 创建list集合 //List<String> lists = Arrays.asList("1", "2", "3"); // 不安全 List<String> lists = new ArrayList<>(); // 开启十个线程增加数据 for (int i = 1; i <= 40; i++) { new Thread(()->{ lists.add(UUID.randomUUID().toString().substring(0,5)); System.out.println(Thread.currentThread().getName()+"=="+lists); },String.valueOf(i)).start(); } } }
When multiple threads operate the same collection of object information, a java.util.ConcurrentModificationException error often occurs. information.
In the Java language, a new List collection, the java.util.Vector class, is provided. See the following code for details:
import java.util.*; public class ListTest { public static void main(String[] args) throws InterruptedException { // 创建list集合 //List<String> lists = Arrays.asList("1", "2", "3"); // 不安全 //List<String> lists = new ArrayList<>(); List<String> lists = new Vector<>(); // 开启十个线程增加数据 for (int i = 1; i <= 40; i++) { new Thread(()->{ lists.add(UUID.randomUUID().toString().substring(0,5)); System.out.println(Thread.currentThread().getName()+"=="+lists); },String.valueOf(i)).start(); } } }
There will be no java.util.ConcurrentModificationException error message.
Why can we ensure the safe operation of data?
Adopts synchronized to lock the method execution caller to ensure the multi-thread security of the add operation!
Under the JUC package, the following ways to create a security collection are provided.
Method 1: Collections.synchronizedList(new ArrayList<>());
import java.util.*; public class ListTest { public static void main(String[] args) throws InterruptedException { List<String> lists = Collections.synchronizedList(new ArrayList<>()); // 开启十个线程增加数据 for (int i = 1; i <= 40; i++) { new Thread(()->{ lists.add(UUID.randomUUID().toString().substring(0,5)); System.out.println(Thread.currentThread().getName()+"=="+lists); },String.valueOf(i)).start(); } } }
View the underlying source code to implement the logic
Determine the incoming list collection type and determine whether the type is java.util.RandomAccess. If so, use java.util.Collections.SynchronizedRandomAccessList to construct the collection. If not, use java.util.Collections.SynchronizedList constructs a collection.
The corresponding add operation logic in the source code is as follows:
Adopt the synchronized synchronization code block method to add data Operation to achieve locking!
Method 2: new CopyOnWriteArrayList();
import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; public class ListTest { public static void main(String[] args) throws InterruptedException { List<String> lists = new CopyOnWriteArrayList<>(); // 开启十个线程增加数据 for (int i = 1; i <= 40; i++) { new Thread(()->{ lists.add(UUID.randomUUID().toString().substring(0,5)); System.out.println(Thread.currentThread().getName()+"=="+lists); },String.valueOf(i)).start(); } } }
The introduction in the source code is as follows:
Obviously, the logic is as follows:
After calling the add method, get java.util.concurrent.locks .ReentrantLock object information.
Call lock.lock() to get the lock!
Copy the original array object and create a new array with the original array size 1.
Put new data into a new array.
Any operation finally will release the lock!
The Lock operation under the JUC package has better performance than synchronized!
The above is the detailed content of How does Java JUC operate a collection of List security classes?. For more information, please follow other related articles on the PHP Chinese website!