The singleton

Hanh: Thread-safe. Class instantiation is triggered when the class is initialized, so only one is guaranteed.

Disadvantages: But can waste memory, if not use singleton, will always exist

public class Singleton {
    // Create a singleton instance in a static initializer. This code is thread-safe
    private static final Singleton instance = new Singleton();
    // The Singleton class has only one constructor and is private, so users cannot create instances of the object through the new method
    private Singleton(a){}
    public static Singleton getInstance(a){
        returninstance; }}Copy the code

Synchronized thread security

public class Singleton {
    private static Singleton instance;
    private Singleton (a){}
    // Versions that do not include the synchronized keyword are thread-safe
    public static synchronized  Singleton getInstance(a) {
        // Check whether the current singleton already exists. If it does, the system returns. If it does not, the system creates a singleton
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
Copy the code

Double check lock: double lock (thread safety)

public class Singleton {
    private static volatile Singleton instance;
    private Singleton(a) {}public static Singleton getInstance(a) {
        if (instance == null) {
            synchronized (Singleton.class){
                if(instance == null){
                    instance = newSingleton(); }}}returninstance; }}Copy the code
  1. The cause of double judgment?
    • The first judgment reduces the use of locks and improves performance
    • Multiple threads are waiting for the lock at the same time, and when the first one is created, there is no need for other threads to repeat the rebuild
  2. The understanding of the volatile
    • Instance retrieval failed due to reordering prohibition (3).
  3. The execution of the new Singleton() method may result in space being allocated, pointing to memory space, but not assigning, which will cause an error if another thread picks it up

Static inner classes :(thread-safe)

public class Singleton {
    // Private constructor
    private Singleton (a){}private static class SingletonHelper{
        // Declare a member variable
        private static final Singleton instance = new Singleton();
    }
    // External interface to obtain the instance
    public static Singleton getSingleton(a){
        returnSingletonHelper.instance; }}Copy the code

Enumeration singleton :(thread-safe)

public enum Singleton {

    INSTANCE;

    public void doSomething(a) {
        System.out.println("doSomething"); }} call method:public class Main {

    public static void main(String[] args) { Singleton.INSTANCE.doSomething(); }} directly through the Singleton. INSTANCE. DoSomething () call. Convenient, simple and safe.Copy the code

Producer consumer

Producers add data, and consumers themselves get information from the middleware, which manages the data

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;

/ * * *@author kangsx
 * @description
 * @date2020/5/13 * /
public class Mode1 {

    static class Box{
        private Queue<Integer> list = new LinkedList<>();
        int maxSize = 50;

        private void put(int i){
            synchronized (this) {while(list.size()>=maxSize){
                    try {
                        wait();
                    } catch(InterruptedException e) { e.printStackTrace(); } } list.add(i); notifyAll(); }}private int get(a){
            int i = 0;
            synchronized (this) {while (list.size()<=0) {try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                i = list.remove();
                notifyAll();
            }
            returni; }}static class Producer extends Thread{
        private Box box;

        public Producer(Box box) {
            this.box = box;
        }

        @Override
        public void run(a) {
            super.run();
            box.put(5); }}static class Consumer extends Thread{
        private Box box;

        public Consumer(Box box) {
            this.box = box;
        }

        @Override
        public void run(a) {
            super.run();
            int i = box.get();
            System.out.println("i = "+ i); }}public static void main(String args[]){
        Box box = new Box();
        //5 producers
        for(int i = 0; i<5; i++) {new Producer(box).start();
        }
        //5 consumers
        for(int i = 0; i<5; i++){newConsumer(box).start(); }}}Copy the code

The observer

Publishers send data to subscribers

import java.util.ArrayList;

/ * * *@author kangsx
 * @description
 * @date2020/5/13 * /
public class Mode2 {
    static public interface IObserver {
        void update(int temp);
    }

    static public interface IObservable {
        void register(IObserver iObserver);

        void unregister(IObserver iObserver);

        void notifyObserver(a);
    }

    // Observed (publisher)
    static class Observable implements IObservable {
        private ArrayList<IObserver> list = new ArrayList<>();
        private int temp;

        @Override
        public void register(IObserver iObserver) {
            list.add(iObserver);
        }

        @Override
        public void unregister(IObserver iObserver) {
            list.remove(iObserver);
        }

        @Override
        public void notifyObserver(a) {
            for (int i = 0; i < list.size(); i++) { list.get(i).update(temp); }}public void setTemp(int temp) {
            this.temp = temp; }}// Observer 1 (subscriber)
    static class Observer1 implements IObserver {

        @Override
        public void update(int temp) {
            System.out.println("Observable1 is updated to ="+ temp); }}// Observer 2(subscriber)
    static class Observer2 implements IObserver {
        @Override
        public void update(int temp) {
            System.out.println("Observable2 is updated to ="+ temp); }}public static void main(String args[]){
        Observable observable = new Observable();
        Observer1 observer1 = new Observer1();
        Observer2 observer2 = new Observer2();
        observable.register(observer1);
        observable.register(observer2);
        observable.setTemp(32131232); observable.notifyObserver(); }}Copy the code

Builder model

Object constructs that provide complex parameters, leaving the parameter configuration entirely to the caller and using the default instead.

public class Computer {
    / / display
    String display;
    / / CPU model
    String cpu;
    // Mainboard model
    String mainBoard;
    // Graphics card model
    String gpu;

    public Computer(Builder builder) {
        this.display = builder.display;
        this.cpu = builder.cpu;
        this.mainBoard = builder.mainBoard;
        this.gpu = builder.gpu;
    }

    @Override
    public String toString(a) {
        return "Monitor is" + display + "\ ncpu is" + cpu + "\n motherboard is" + mainBoard + "\n Graphics card is" + gpu;
    }

    static class Builder{
        / / display
        String display;
        / / CPU model
        String cpu;
        // Mainboard model
        String mainBoard;
        // Graphics card model
        String gpu;

        public Builder(a){
            this.display = "Samsung Curved screen";
            this.cpu = "i5 8400";
            this.mainBoard = "Asus Z360 - B";
            this.gpu = "GTX 1050Ti";
        }

        public Builder setDisplay(String display) {
            this.display = display;
            return this;
        }

        public Builder setcpu(String cpu) {
            this.cpu = cpu;
            return this;
        }

        public Builder setMainBoard(String mainBoard) {
            this.mainBoard = mainBoard;
            return this;
        }

        public Builder setGpu(String gpu) {
            this.gpu = gpu;
            return this;
        }

        public Computer build(a){
            return new Computer(this); }}public static void main(String args[]){
        Computer computer = new Computer.Builder()
                .setcpu("i9 4700u")
                .setGpu("GTX 2060Ti")
                .setMainBoard("Asus Z480") .build(); System.out.println(computer.toString()); }}Copy the code

The factory pattern

The proxy pattern

To encapsulate the original function, the access object can not directly access the original function, only access our function communication, we are the agent, as the intermediary between the original function and the access object

Static proxy:

package proxy;

public class ProxyTest {
    public static void main(String[] args) {
        Proxy proxy = newProxy(); proxy.Request(); }}// Abstract theme
interface Subject {
    void Request(a);
}

// True theme
class RealSubject implements Subject {
    public void Request(a) {
        System.out.println("Access real topic methods..."); }}/ / agent
class Proxy implements Subject {
    private RealSubject realSubject;

    public void Request(a) {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        preRequest();
        realSubject.Request();
        postRequest();
    }

    public void preRequest(a) {
        System.out.println("Pre-processing before accessing the real subject.");
    }

    public void postRequest(a) {
        System.out.println("Follow-up after accessing the real topic."); }}Copy the code

Dynamic proxy:

IRetrofit iRetrofit = (IRetrofit) Proxy.newProxyInstance(IRetrofit.class.getClassLoader(), newClass<? >[]{IRetrofit.class},new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("----- execute before call");
                if(method.getDeclaringClass() == Object.class) {
                    System.out.println("----- Execute Object before calling");
                    return method.invoke(IRetrofit.class, args);
                }
                IRetrofit iRetrofit1 = new IRetrofit() {
                    @Override
                    public void test(a) {
                        System.out.println("------test1");
                    }

                    @Override
                    public void kang(a) {
                        System.out.println("------kang1"); }}; Object object = method.invoke(iRetrofit1,args); System.out.println("------- execute after call");
                return null; }}); iRetrofit.kang();Copy the code

Print the following:

------kang1 ------- is executed after ----- is invokedCopy the code

That is, you can call that method if you want. We proxy it on Invoke and execute the class using reflection