preface

In the daily development process, List is a collection we commonly use, such as query database content return value ratio will use a collection, but under the condition of multi-thread concurrent, will there be security issues? Let’s test how to resolve security issues if they arise.

The List collection uses simulated concurrency tests

1.1 Single threaded environment

Public static void main(String[] args) {// ArrayList< String bb0 List = new ArrayList<>(); // insert for (int I = 0; i < 10; I++) {list. Add (UUID. RandomUUID (), toString (). The substring (0, 5)); System.out.println(list); }}

We can see that in a single thread, we can insert a list without any problem. Now let’s simulate what happens when we run it concurrently.

1.2 Multithreaded environment

Public static void main(String[] args) {// ArrayList< String bb0 List = new ArrayList<>(); // insert for (int I = 0; i < 10; I++) {new Thread(()->{list.add(uuid.randomuuid ().toString().substring(0,5)); System.out.println(list); }, "thread List"). The start (); }}

ArrayList if to be modified at the same time when I was in the iteration will be thrown Java. Util. ConcurrentModificationException abnormalities, abnormal is concurrent modification.

Second, solutions

2.1 Use the Vector class

Public static void main(String[] args) {List<String bb0 List = new Vector<>(); // insert for (int I = 0; i < 10; I++) {new Thread(()->{list.add(uuid.randomuuid ().toString().substring(0,5)); System.out.println(list); }, "thread List"). The start (); }}

Vector is accessed synchronously, and its add method is modified with the synchronized keyword.

Test results:

2.1 the use of the Collections. SynchronizedList

Public static void main (String [] args) {/ / the List collection a List < String > List = Collections. SynchronizedList (new ArrayList < > ()); // insert for (int I = 0; i < 10; I++) {new Thread(()->{list.add(uuid.randomuuid ().toString().substring(0,5)); System.out.println(list); }, "thread List"). The start (); }}

A look at the underlying source code reveals that he also uses the synchronized keyword modification.

2.3 Use the concurrent container CopyOnWriteArrayList

Public static void main(String[] args) {// List<String bb0 List = new CopyOnWriteArrayList<>(); // insert for (int I = 0; i < 10; I++) {new Thread(()->{list.add(uuid.randomuuid ().toString().substring(0,5)); System.out.println(list); }, "thread List"). The start (); }}

Look at the source code. It uses the lock mechanism.

Copy while writing, when there are multiple threads calling, when writing, copy a copy, to avoid overwriting caused data problems. So instead of making any changes to the original set, you just make a new copy of it, and then you move the pointer when you’re done.

Starting with JDK1.5, Java provides two concurrent containers that use the CopyOnWrite mechanism in the package. They are CopyOnWriteArrayList and CopyOnWriteArraySet. The CopyonWrite container is very useful and can be used in a wide variety of concurrent scenarios.

Read the source code:

/** * Appends the specified element to the end of this list. * * @param e element to be appended to this list * @return {@code true} (as specified by {@link Collection#add}) */ public boolean add(E e) { final ReentrantLock lock = this.lock; // Reentrant lock Lock.lock (); GetArray (); getArray(); getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); NewElements [len] = e; setArray(newElements); Return true; // return true; } finally { lock.unlock(); // Unlock}}

Add () adds a lock to the collection to ensure synchronization and avoid multiple threads writing to Copy N copies.

conclusion

CopyOnWriteArrayList usage scenario: Read more and write less (whitelist, blacklist, commodity class access and update scenario), set is small. So in general, we will use the thread-safe containers provided under the JUC package, rather than the older generation of thread-safe containers.