싱글 톤 모드 구현 (5 유형)
일반적으로 사용 :
배고픈 스타일 (스레드 안전하고 고속 호출 효율성이지만 지연된 방식으로로드 할 수는 없습니다)
게으른 스타일 (스레드 안전, 낮은 통화 효율은 지연시로드 할 수 있습니다)
다른:
Double Detection Lock 유형 (JVM의 기본 내부 모델로 인해 때때로 문제가 있으며 구축 및 사용되지 않습니다).
정적 내부 클래스 (스레드-안전, 높은 통화 효율이지만 지연된 방식으로로드 할 수 있음)
싱글 톤을 열거하고 (스레드-안전, 높은 통화 효율성, 지연시로드 할 수 없음)
배고픈 사람의 싱글 톤의 특정 코드는 다음과 같습니다.
패키지 com.lcx.mode; /** * * 배고픈 사람들의 싱글 톤. 이 객체가 미래에 사용되는지 여부에 관계없이 처음 부터이 객체의 인스턴스를 만듭니다. * 필요할 때 생성 인스턴스 객체를 반환하므로 상대적으로 배가 고프므로 배고픈 사람들의 싱글 톤이라고합니다. * @Author QQ1013985957 */ Public Class SingletonHanger {Private Static Final SingletonHanger 인스턴스 = New SingletonHanger (); Private SingletonHanger () {} public static singletonHanger getInstance () {return instance; }} /*** Lazy Han 스타일의 싱글 톤, 싱글 톤 객체가 필요할 때 유일한 싱글 톤 객체를 만들고 나중에 다시 호출 할 수 있으며, 반환 된 싱글 톤 객체는 또한 처음으로 만든 싱글 톤 객체입니다. * @Author qq1013985957 * */ class singletonlazy {private static singletonlazy instance = null; Private SingletonLazy () {} /***이 방법에 의해 구현 된 싱글 톤은 여러 스레드에서 사용할 수 없습니다. 여러 줄은 동시에 IF 메소드를 입력 할 수 있으므로 여러 개의 싱글 톤 객체가 생성됩니다. * @return */ public static singletonlazy getInstance1 () {if (instance == null) {instance = new SingletonLazy (); } return 인스턴스; } /*** 모든 사람은 동기화를 생각할 것입니다. 동기 방법은 다중 스레드 싱글 톤*을 구현할 수 있지만이 방법은 바람직하지 않으며 성능에 심각한 영향을 미칩니다. 싱글 톤을 얻을 때마다 메소드를 점검해야하므로 동기화 된 코드 블록 만 사용하여 동기화를 달성 할 수 있습니다. * @return */ public static synchronized singletonlazy getInstance2 () {if (instance == null) {instance = new SingletonLazy (); } return 인스턴스; } /*** 동기화 된 코드 블록을 사용하여 IF 메소드의 동기화 된 코드 블록을 사용하여 싱글 톤이 존재하는지 여부를 결정하고 싱글 톤이 생성되었는지 동기화 된 코드 블록에서 다시 확인하십시오. * 이것은 인터넷에서 이중 점검 잠금 방법 */ public static synchronized singletonlazy getInstance3 () {if (instance == null) {synchronized (singletonlazy.class) {if (instance == null) {instance = new SingletonLazy (); }}} return 인스턴스; }} /*** 열거를 사용하여 싱글 톤 모드를 구현하는데, 이는 특정 상황에 따라 효과적인 Java* 인스턴스화에 사용하는 권장 방법이기도합니다. 열거에 익숙하지 않은 학생들의 경우 내 블로그 Java 열거 수업에 대한 예비 이해를 참조하십시오. * 그것의 이점 : 복잡한 시퀀스 및 반사 공격에 직면하더라도 더 간결하고 자유롭게 직렬화 메커니즘을 무료로 제공합니다. * @Author qq1013985957 * */ enum singletionenum {Singletionenum ( "Singleton enum"); 개인 문자열 str; Private SingletionEnum (String Str) {this.setstr (str); } public String getstr () {return str; } public void setstr (String str) {this.str = str; }} 위의 싱글 톤 패턴은 테스트되지 않습니다. 객체의 해시 코드가 동일한 객체인지 결정하기 위해 일관된 지 여부를 결정하기 위해 테스트 할 수 있습니다.
악하고 게으른 방법은 반사가 여러 인스턴스를 구현하는 것을 막을 수 없습니다. 반사를 통해 액세스 가능한 설정을 설정하십시오 .setAccessible 메소드는 개인 생성자를 호출 할 수 있습니다. 두 번째 인스턴스를 작성하라는 요청이있을 때 생성자를 수정하여 예외를 던질 수 있습니다.
실제로 이것은 싱글 톤을 보장 할 수 없습니다. 직렬화 후, 사형화는 새로운 인스턴스를 생성하고 싱글 톤 클래스에 readresolve () 메소드를 추가하여 방지 할 수 있습니다.
게으른 남자 스타일의 싱글 톤 코드는 다음과 같습니다.
패키지 com.lcx.mode; import java.io.file; import java.io.fileInputStream; import java.io.fileoutputStream; import java.io.objectinputstream; import java.io.objectoutputStream; java.io.serializable import; java.lang.reflect.constructor import; import java.lang.reflect.invocationTargetexception; /*** 게으른 남자 스타일의 싱글 톤은 싱글 톤 객체가 필요할 때 만들어집니다. 싱글 톤 객체가 필요한 경우 나중에 다시 호출됩니다. 반환 된 싱글 톤 객체는 또한 처음으로 만든 싱글 톤 객체이기도합니다* 정적 멤버를 null로 초기화하고 싱글 톤을 얻을 때이를 생성하므로 게으른 남자 스타일이라고합니다. * @Author QQ1013985957 * */ Public Class Singleton은 직렬화 가능 {/ ** */ private static final long serialversionuid = -527153727137321645L; 개인 정적 싱글 톤 인스턴스 = null; 개인 정적 int i = 1; Private Singleton () { / *** 반사 공격 방지, 생성자를 한 번만 실행하고 호출하고 두 번째로 예외를 던지십시오* / if (i == 1) {i ++; } else {Throw new runtimeexception ( "생성자는 한 번만 호출 할 수 있습니다"); } system.out.println ( "싱글 톤의 개인 생성자"); } /*** 동기화 된 코드 블록을 사용하여 IF 메소드의 동기화 된 코드 블록을 사용하여 싱글 톤이 존재하는지 여부를 결정하고 싱글 톤이 생성되었는지 동기화 된 코드 블록에서 다시 확인하십시오. * 이것은 인터넷이 이중 점검 잠금 방법을 호출하는 것입니다 * @return */ public static synchronized singleton getInstance () {if (instance == null) {synchronized (singleton.class) {if (instance == null) {instance = new Singleton (); }} return instance; } /*** Desequence가 새로운 싱글 톤 객체를 생성하는 것을 방지합니다. 이것은 책에서 효과적인 Java에서 말하는 것입니다. 이 방법을 방지 할 수 있습니다. 특정 세부 사항을 이해하지 못합니다 * @return */ private 객체 readResolve () {return instance; } public static void main (String [] args)은 예외 {test1 (); test2 (); } / *** 테스트 desequence는 여전히 싱글 톤 모드입니다* @throws 예외* / public static void test2 ()는 예외를 던지려고 {Singleton s = singleton.getInstance (); ObjectOutputStream ObjectOutputStream = new ObjectOutputStream (new FileOutputStream (새 파일 ( "e : //singleton.txt")); ObjectOutputStream.writeObject (s); ObjectInputStream ObjectInputStream = new ObjectInputStream (new FileInputStream (새 파일 ( "e : //singleton.txt")); 객체 readObject = ObjectInputStream.readoBject (); 싱글 톤 S1 = (싱글 톤) readObject; System.out.println ( "s.hashcode () :"+s.hashcode ()+", s1.hashcode () :"+s1.hashcode ()); ObjectOutputStream.flush (); ObjectOutputStream.close (); ObjectInputStream.close (); ObjectInputStream.close (); } / *** 테스트 반사 공격* @Throws Exception* / public static void test1 () {Singleton S = Singleton.getInstance (); 클래스 C = Singleton.class; 생성자 privateconstructor; try {privateConstructor = c.getDeclaredConstructor (); privateconstructor.setAccessible (true); privateconstructor.newinstance (); } catch (예외 e) {e.printstacktrace (); }}}반사 공격 결과 확인 :
readResolve 방법의 결과가 추가되지 않으면 다음과 같습니다.
readResolve 방법을 추가 한 결과 :
읽어 주셔서 감사합니다. 도움이되기를 바랍니다. 이 사이트를 지원 해주셔서 감사합니다!