Memory overflow problem + singleton mode + custom blocking queue

ThreadLocal uses:
1.set: set the private variable to the thread
2.get: get ThreadLocal from thread
3.remove: remove ThreadLocal from the thread.
4.initialValue: initialization
5.withInitialValue: initialization (lambda expression)

Usage scenario:
1. Solve thread safety problems
2. Realize thread level data transmission

Disadvantages:
1. Data transfer between parent and child threads cannot be performed.
2. Dirty data. ThreadLocal + thread pool (reuse)
3. Memory overflow

Memory overflow problem

Set the maximum running memory to 5M

package threadPool0523;

import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolDemo20 {

    //1M size object
    static class OOMObject{
        private byte[] bytes=new byte[1*1024*1024];
    }
    static ThreadLocal<OOMObject> threadLocal=new ThreadLocal<>();

    public static void main(String[] args) throws InterruptedException {
        ThreadPoolExecutor executor=new ThreadPoolExecutor(10,10,0, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>());

        for (int i = 0; i <5 ; i++) {
            int finalI=i;
            executor.execute(new Runnable() {
                @Override
                public void run  () {
                    OOMObject oomObject=new OOMObject();
                    //set ThreadLocal
                    System.out.println("task"+finalI+"Yes!");
                    threadLocal.set(oomObject);
                    //No more objects
                    oomObject=null;
                }
            });
            //t.start();
            Thread.sleep(200);
        }
    }
}

Problem analysis:
The thread pool has a long life cycle. When a thread finishes executing a task, the thread ends (the resources related to the thread will be released).


Interview questions:
What is the difference between HashMap and ThreadLocalMap in handling hash conflicts?
hashmap uses the linked list method, while ThreadLocalMap uses the open addressing method

Why is it so?
A: the characteristics and usage scenario of open addressing method is that the performance is better when the data volume is less than the price.
The hashmap usually stores a lot of data, and the open addressing method is inefficient. It is best to use the linked list method.



Why set the key in ThreadLocal as weak reference?
To avoid OOM for maximum length


Solve the memory overflow of ThreadLocal?
Use remove ().

Improve program performance:
1. Multithreading
2. Singleton mode

Design mode:
1. Singleton mode (handwriting)
2. Factory mode (simple factory, abstract factory)
3. Template mode

Singleton mode:
Only one object is stored in the operation of the whole program

1: Method: create objects directly (thread safe)

/**
 * Hungry man model
 */
package ThreadDemo0603;
class Singleton{
    //1. Create a private constructor (prevent other classes from creating directly)
    private  Singleton(){
    }

    //2. Define private variables (thread safety)
    private  static  Singleton singleton=new Singleton();

    //3. Provide public methods for obtaining instances
    public static Singleton getInstance(){
        return singleton;
    }
}

public class ThreadDemo01 {

    public static void main(String[] args) {
        Singleton singleton=Singleton.getInstance();
        System.out.println(singleton);

    }
}

Disadvantages: the program is created after startup and may not be used, thus wasting system resources.

Lazy way: when the program starts, it will not initialize, but when to call and when to initialize

Custom blocking queue: linked list and array

/**
 * Custom blocking queue
 */
package ThreadDemo0603;

import java.util.Random;

public class ThreadDemo06 {
    static class MyBlockingQueue{
        private int[] values;//Array of actual stored data
        private int first;//Team leader
        private int last;//Team tail
        private int size;//Actual size of queue element
        public MyBlockingQueue(int initial){
            //initialize variable
            values=new int[initial];
            first=0;
            last=0;
            size=0;

        }
        //Add element (add to end of queue)
        public void offer(int val){
            synchronized (this){
                //Judge whether it is full
                if(size==values.length){
                    //Queue full
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //Add element to end of queue
                values[last++]=val;
                size++;
                //Determine whether it is the last element
                if(last==values.length){
                    last=0;
                }
                //Try to wake up consumers
                this.notify();
            }
        }
        //Query method
        public int poll(){
            int result=-1;
            synchronized (this){
                //Judgment boundary value
                if(size==0){
                    //Queue is empty, blocking waiting
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //Take element
                result=values[first++];
                size--;
                //Determine whether it is the last element
                if(first==values.length){
                    first=0;
                }
                //Try to wake up the producer
                this.notify();
            }

            return result;
        }
    }

    public static void main(String[] args) {
        MyBlockingQueue myBlockingQueue=new MyBlockingQueue(100);
        Thread t1=new Thread(new Runnable() {
            @Override
            public void run() {
                //One piece of data is produced every 500ms
                while(true){
                    int num=new Random().nextInt(10);
                    System.out.println("Random number generated:"+num);
                    myBlockingQueue.offer(num);
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t1.start();
        //Create consumer

        Thread t2=new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                   int result=myBlockingQueue.poll();
                    System.out.println("Consumption data"+result);
                }
            }
        });
        t2.start();
    }
}

Keywords: Java Multithreading

Added by optik on Wed, 02 Feb 2022 04:13:52 +0200