2022 인터뷰 Android 싱글톤 모드

싱글톤 모드는 게으른 사람 모드와 배고픈 사람 모드의 두 가지 범주로 크게 나눌 수 있지만 게으른 사람인지 배고픈 사람인지 신경 쓸 필요는 없지만 여전히 그 원리와 차이점을 이해해야 합니다. (게으른 사람이란 클래스가 로드된 후 싱글톤이 인스턴스화되지 않고 처음 사용할 때까지 지연되는 것을 의미하고, 악당이란 클래스가 로드되고 싱글톤이 인스턴스화되는 것을 의미합니다.)

이 문서의 예제는 모두 스레드로부터 안전한 싱글톤 패턴입니다.

코드와 주석을 직접 살펴보십시오.

1. 이중 잠금 싱글톤 모드(게으른 사람 모드)

이 모드는 코드가 이해하기 쉽고 가비지 개체를 생성하지 않는 지연 로드 모드이기 때문에 이전에 작성자가 가장 일반적으로 사용하는 모드이기도 합니다. 기본 인터뷰에서 이 모드가 먼저 응답되며, 이 모드는 휘발성 및 동기화 잠금의 역할을 포함하여 많은 지식 포인트를 확장할 수 있습니다.

/**
 * 双层加锁的单例模式
 * */
public class SingletonTest3 implements Test{
    /**
     * instance使用volatile修饰,防止线程之间出现脏数据,导致线程A已经执行完instance = new SingletonTest3() ;
     * 后线程B拿到锁,但是判断instance还是null,而导致instance初始化两次。
     */
    private volatile static SingletonTest3 instance = null ;

    private SingletonTest3(){
        Log.d("gggl" , "SingleTest3 初始化了") ;
    }

    public static SingletonTest3 getInstance(){
        //首先进行instance的null判断,为了在没有线程竞争的情况下提高速度不必进行锁的竞争。
        if (instance == null) {
            //加锁防止线程竞争
            synchronized (SingletonTest3.class) {
                //二次判断,这里是必须的,因为第一个null判断不是线程安全的。
                if (instance == null) {
                    instance = new SingletonTest3() ;
                }
            }
        }
        return instance ;
    }

    @Override
    public void test() {
        Log.d("gggl" , "SingletonTest3 初始化了") ;
    }
}

2. 정적 최종 멤버 변수 인스턴스 수정(빌런 모드)

이 모드에서는 클래스가 메모리에 로드될 때 생성자가 호출됩니다.싱글톤 프로젝트가 시작된 후 항상 필요한 경우 이 방법에 문제가 없으며 간단하고 편리합니다. 그러나 프로젝트가 시작된 후 특정 작업에 의해 싱글톤이 트리거되어야 하는 경우 이 방법은 권장되지 않으며 약간의 메모리가 낭비됩니다. 사실 제가 좀 까다롭긴 한데 이건 면접이니까 진지하게 하세요. -^-

import com.example.interview.Test;

public class SingletonTest1 implements Test {
    private SingletonTest1(){
        Log.d("gggl" , "SingletonTest1 初始化了")  ;
    }
    private static final SingletonTest1 instance = new SingletonTest1() ;

    public static SingletonTest1 getInstance() {
        return instance ;
    }
    public void test(){
        Log.d("gggl" , "SingletonTest1 say hello!!!!") ;
    }
}

3. 정적 내부 클래스 모드(게으른 사람 모드)

정적 내부 클래스 패턴. 이 모드는 약간 책임이 있으며 저자는 기본적으로 첫 번째 이중 null 판단 모드를 사용하기 때문에 사용하는 것을 좋아하지 않습니다. 하지만 인터뷰를 위해 나갈 방법이 없습니다. 그냥 살펴보십시오.


public class SingletonTest1 implements Test {
    private SingletonTest1(){
        Log.d("gggl" , "SingletonTest1 初始化了")  ;
    }

    public static SingletonTest1 getInstance() {
        return SingletonHander.singleton ;
    }
    public void test(){
        Log.d("gggl" , "SingletonTest1 say hello!!!!") ;
    }
    private static class SingletonHander{
        private static final SingletonTest1 singleton = new SingletonTest1 ();
    }
}

테스트 코드:

try {
            Class.forName("com.example.interview.designpattern.SingletonTest1" , true , getClassLoader()) ;
            Log.d("gggl" , "SingletonTest1加载完毕") ;
            Class.forName("com.example.interview.designpattern.SingletonTest2" , true , getClassLoader()) ;
            Log.d("gggl" , "SingletonTest2加载完毕") ;
            Class.forName("com.example.interview.designpattern.SingletonTest3" , true , getClassLoader()) ;
            Log.d("gggl" , "SingletonTest3加载完毕") ;
            SingletonTest1.getInstance().test();
            SingletonTest2.getInstance().test();
            SingletonTest3.getInstance().test();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

여기에서 먼저 SingletonTest의 여러 클래스를 로드합니다(참고: 이 단계에서 Class.가 수행되는 경우). 그런 다음 각각 SingletonTest.getInstance().test() 메서드를 호출합니다. 실행 결과를 살펴보자.

2022-09-16 10:16:01.081 11710-11710/com.example.interview D/gggl: SingletonTest1 初始化了
2022-09-16 10:16:01.081 11710-11710/com.example.interview D/gggl: SingletonTest1加载完毕
2022-09-16 10:16:01.082 11710-11710/com.example.interview D/gggl: SingletonTest2加载完毕
2022-09-16 10:16:01.082 11710-11710/com.example.interview D/gggl: SingletonTest3加载完毕
2022-09-16 10:16:01.082 11710-11710/com.example.interview D/gggl: SingletonTest1 say hello!!!!
2022-09-16 10:16:01.082 11710-11710/com.example.interview D/gggl: SingletonTest2 初始化了
2022-09-16 10:16:01.082 11710-11710/com.example.interview D/gggl: SingletonTest2 say hello!!!!
2022-09-16 10:16:01.082 11710-11710/com.example.interview D/gggl: SingleTest3 初始化了
2022-09-16 10:16:01.082 11710-11710/com.example.interview D/gggl: SingletonTest3 初始化了

SingletonTest1이 Hungry Man 모드의 첫 번째 유형(private static final SingletonInstance1 = new SingletonInstance1())이고 클래스가 로드될 때 생성자가 실행되는 것을 보셨습니다.

요약하다:

사실 개발할 때 위의 3가지 모드는 1, 3만 쓰면 되고, 2번째 모드는 레이지로드 모드가 아니니 사용하지 않도록 해보세요. 인터뷰를 위해서는 위의 세 가지 모드를 아는 것으로 충분하며 스레드로부터 안전하지 않은 가장 간단한 모드는 작성하지 마십시오.

추천

출처blog.csdn.net/mldxs/article/details/126885496