From the pit! CopyOnWriteArrayList has to be sorted like this!

1. Scene Description

Multiple threads add integer content to a List. When all processes are finished, the sorting result of the List is printed

Second, CopyOnWriteArrayList

If you want to implement the above scenario, you will first think of using the collection CopyOnWriteArrayList as a List. Here’s a brief introduction to CopyOnWriteArrayList

Concurrency issues arise with ArrayList because there are no locks for multithreaded access, so CopyOnWriteArrayList is a good place to consider.

As can be seen from the name, this List is copied on write. The principle is that when an element needs to be added, a copy of the original element is made.

Using CopyOnWriteArrayList not only solves the container concurrency problem, but also becomes more efficient when writing less and reading more. CopyOnWriteArrayList is efficient in another way, because it writes without locking.

Third, the recurrence of problems

1. Defect code

This code is implemented in the JDK6 environment “multithreaded add content to print the List sort result”, the code can be: 1. Each thread is doing “add 100 random numbers from 0 to 1000” 3. 4. Finally print the sorted list result

package com.inspire.pro;

import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;

public class Test2 {
    public static void main(String[] args) {
        final List<Integer> list = new CopyOnWriteArrayList<Integer>();
        final Random r = new Random();
        Thread[] threads = new Thread[100];/ / 100
        for (int i = 0; i < threads.length; i++) {
            Runnable task = new Runnable() {
                @Override
                public void run(a) {
                    for (int i = 0; i < 100; i++) {/ / 1000
                        list.add(r.nextInt(1000));//nextInt(int n) Generates a random int between [0,n).} Collections.sort(list); }}; threads[i] =new Thread(task);
        }
        runAndComputeTime(threads);
        System.out.println(list.size());
        System.out.println(list);

    }

    public static void runAndComputeTime(Thread[] threads) {
        long s1 = System.currentTimeMillis();
        for(int i=0; i<threads.length; i++){ threads[i].start(); }for(int i=0; i<threads.length; i++){try {
                threads[i].join();
            } catch(InterruptedException e) { e.printStackTrace(); }}long s2 = System.currentTimeMillis();
        System.out.println(s2 - s1 + "ms"); }}Copy the code

2. Running result

Throw an error message: Java. Lang. UnsupportedOperationException

4. Cause analysis

Operation exceptions are not supported. Take a look at the error stack on the third line, click into the source code, and point to the exception thrown by set here

In other words, is it true that the iterator we passed in CopyOnWriteArrayList does not support set? Let’s go back to the source code for verification. Click listIterator() on line 116 and use the shortcut CTRL + Alt +B to view the methods that implement the listIterator interface to find CopyOnWriteArrayList

Click to see that this interface returns the iterator COWIterator of CopyOnWriteArrayList

Click on this class, go to set, and you’ll see if CopyOnWriteArrayList supports set

Sure enough, CopyOnWriteArrayList iterators do not support set methods. The set method is not supported for this iterator.) Collections.sort(List) does not support sorting CopyOnWriteArrayList

5. Code improvement

The improved code looks like this

The point of change is to change the original collections.sort (list); replace

List lineList = Arrays.asList(list.toArray());
Collections.sort(lineList);
list.clear();
list.addAll(lineList);
Copy the code

1. Convert CopyOnWriteArrayList to ArrayList 2. Sort using the Collections sort method that supports ArrayList, and of course, the sorted results are kept in lineList 3. Delete CopyOnWriteArrayList. 4. Add the sorted lineList elements to CopyOnWriteArrayList

The complete code is as follows

package com.inspire.pro;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;

public class Test2 {
    public static void main(String[] args) {
        final List<Integer> list = new CopyOnWriteArrayList<Integer>();
        final Random r = new Random();
        Thread[] threads = new Thread[100];/ / 100
        for (int i = 0; i < threads.length; i++) {
            Runnable task = new Runnable() {
                @Override
                public void run(a) {
                    for (int i = 0; i < 100; i++) {/ / 1000
                        list.add(r.nextInt(1000));
                    }
                    //Collections.sort(list); Collections.sort(List) does not support sorting CopyOnWriteArrayListList lineList = Arrays.asList(list.toArray()); Collections.sort(lineList); list.clear(); list.addAll(lineList); }}; threads[i] =new Thread(task);
        }
        runAndComputeTime(threads);
        System.out.println(list.size());
        System.out.println(list);

    }

    public static void runAndComputeTime(Thread[] threads) {
        long s1 = System.currentTimeMillis();
        for(int i=0; i<threads.length; i++){ threads[i].start(); }for(int i=0; i<threads.length; i++){try {
                threads[i].join();
            } catch(InterruptedException e) { e.printStackTrace(); }}long s2 = System.currentTimeMillis();
        System.out.println(s2 - s1 + "ms"); }}Copy the code

* If you have any questions in the process, you can pay attention to the wechat public number “Program Art Room”, add my wechat to consult me * One Health three lian Oh!