Case 15 – Creating a large number of objects causes the CPU to soar

Directory

1. Background introduction

1. Read data splicing url address from reids, there is a problem of incomplete splicing of addresses

2. In the case of concurrency, a large number of objects will be created, causing the CPU to soar

2. Analyzing the problem

3. How to solve

Problem recurrence

1. Operation class

2. Start the class and use 100 threads to simulate the concurrent situation

3. As a result of the operation, there is data confusion.

Solve the problem

1. Use synchronized to optimize code

2. Use ThreadLocal

3. Use the removeAll method to solve the problem of creating a large number of objects

4. Summary and improvement


1. Background introduction

1. Read data splicing url address from reids, there is a problem of incomplete address splicing

2. In the case of concurrency, a large number of objects will be created, causing the cpu to soar

2. Analyze the problem

The two questions are contextual. When there are concurrent requests to the business, since keyList is a global variable, other methods will also operate on it, so there will be one method that has not finished operating the second one. A method followed by another operation. In the end, the key value we spliced out cannot be read in redis. As a result, the problem of splicing url addresses has arisen. For the generation of a large number of objects, it is also caused by concurrency. The first object has just been created, and then the second object has been created. And because the object was copied to a public variable, the previous object lost its reference, waiting for the garbage collector to recycle. As a result, the cpu soared in a straight line.

3. How to solve it

Reproduce the problem

1. Operation class

public class Count {
    List<String> content=new ArrayList<>();

    public void getContent(){
        content = new ArrayList<>();
        content.add("1");
        content.add("2");
        content.add("3");
        content.add("4");
        System.out.println("wzill" + content);
    }
}

2. Start class, use 100 threads to simulate concurrency

public class Client {
    public static void main(String[] args) {
        // Define thread implementation interface
        Runnable runnable = new Runnable(){
            Count counter = new Count();

            @Override
            public void run() {
                try {
                    counter. getContent();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        };
        // start 100 threads
        for(int i= 0;i< 100;i ++ ) {
            new Thread(runnable).start();
        }
    }
}

3. As a result of the operation, data confusion occurred.

Solve the problem

1. Use synchronized to optimize code

Only one thread is executing at a time to ensure the security of thread data.

public class Count {
    List<String> content=new ArrayList<>();

    public synchronized void getContent(){
        content = new ArrayList<>();
        content.add("1");
        content.add("2");
        content.add("3");
        content.add("4");
        System.out.println("wzill" + content);
    }
}

2. Use ThreadLocal

public class Count {
    private static ThreadLocal<List<String>> keyList = new ThreadLocal<List<String>>(){
        //Initialize the keyList
        @Override public List<String> initialValue() {
            return new ArrayList<String>();
        }
    };

    public synchronized void getContent(){

        keyList.get().add("1");
        keyList.get().add("2");
        keyList.get().add("3");
        keyList.get().add("4");
        System.out.println("wzill" + keyList.get());
    }
}

3. Use the removeAll method to solve the problem of creating a large number of objects

//declare a global variable, ArrayList thread is not safe
    List<String> keyList=new ArrayList<>();
    public synchronized void count2() throws InterruptedException {
        keyList.add("a");
        keyList.add("b");
        keyList.add("c");
        keyList.add("d");
        System.out.println("ARPRO" + keyList);
        //Since the count2() method is locked using synchronized, only one thread is executed at the same time
        //But threads share global variables, so after the method is executed, the value of keyList needs to be restored
        keyList. removeAll(keyList);

       }

4. Summary improvement

Be careful when using global variables, consider his scope and what it affects. Add the necessary description, because the scope is large, others can also use this variable, reducing the impact of other people’s use on the previous business.