개념:
Java의 싱글 톤 패턴은 일반적인 디자인 패턴입니다. 싱글 톤 패턴은 게으른 싱글 톤, 배고픈 싱글 톤 및 등록 된 싱글 톤의 세 가지 유형으로 나뉩니다.
싱글 톤 모드에는 다음과 같은 특성이 있습니다.
1. 싱글 톤 클래스에는 하나의 인스턴스 만있을 수 있습니다.
2. 싱글 톤 클래스는 고유 한 인스턴스를 만들어야합니다.
3. 싱글 톤 클래스는이 인스턴스를 다른 모든 객체에 제공해야합니다.
싱글 톤 패턴은 클래스에 하나의 인스턴스 만 있도록하고 자체적으로 인스턴스를 인스턴스화 하고이 인스턴스를 전체 시스템에 제공합니다. 컴퓨터 시스템에서 스레드 풀, 캐시, 로그 객체, 대화 상자, 프린터 및 그래픽 카드의 드라이버 객체는 종종 싱글 톤으로 설계됩니다. 이러한 응용 프로그램에는 리소스 관리자의 기능이 어느 정도 있습니다. 각 컴퓨터에는 여러 프린터가있을 수 있지만 동시에 프린터에 두 개의 인쇄 작업이 출력되는 것을 피하기 위해 하나의 프린터 스풀러 만 사용할 수 있습니다. 각 컴퓨터에는 여러 통신 포트가있을 수 있으며 시스템은 두 개의 요청에 의해 하나의 통신 포트가 동시에 호출되는 것을 피하기 위해 이러한 통신 포트를 중앙에서 관리해야합니다. 요컨대, 싱글 톤 모델을 선택하는 것은 일관되지 않은 상태를 피하고 정치적 강세를 피하는 것입니다.
다음은 두 가지 유형의 소개입니다 : 게으르고 배고픈
1. 즉시로드/배고픈 스타일
메소드를 호출하기 전에 인스턴스가 작성되었습니다.
package com.weishiyao.learn.day8.singleton.ep1; public class myObject {// 지금로드 == evil mode private static myObject myObject = new myObject (); private myObject () {} public static myObject getInstance () {//이 코드 버전이 지금로드 중입니다. // 코드 의이 버전의 단점은 다른 인스턴스 변수가있을 수 없다는 것입니다. }} 스레드 클래스를 만듭니다
package com.weishiyao.learn.day8.singleton.ep1; public class mythread는 스레드 {@override public void run () {system.out.println (myObject.getInstance (). hashcode ()); }} 런 클래스를 만듭니다
패키지 com.weishiyao.learn.day8.singleton.ep1; public class run {public static void main (string [] args) {mythread t1 = new Mythread (); Mythread T2 = New Mythread (); Mythread T3 = New Mythread (); t1.start (); t2.start (); t3.start (); }} 실행 결과
167772895
167772895
167772895
해시 코드는 동일한 값이므로 객체도 동일하다는 것을 의미합니다. 즉, 즉각적인 로딩 모드가 구현되었음을 의미합니다.
2. 게으른 하중/게으른
메소드가 호출 된 후 인스턴스가 생성됩니다. 구현 계획은 매개 변수가없는 생성자에 인스턴스화를 배치하여 메소드의 인스턴스가 메소드가 호출 될 때만 생성되는 것입니다. 암호:
패키지 com.weishiyao.learn.day8.singleton.ep2; public class myobject {private static myobject myobject; private myObject () {} public static myObject getInstance () {// 지연로드 If (myObject! = null) {} else {myObject = new myObject (); } return myObject; }} 스레드 클래스를 만듭니다
package com.weishiyao.learn.day8.singleton.ep2; public class mythread는 스레드 {@override public void run () {system.out.println (myObject.getInstance (). hashcode ()); }} 런 클래스를 만듭니다
패키지 com.weishiyao.learn.day8.singleton.ep2; public class run {public static void main (String [] args) {Mythread T1 = new Mythread (); t1.start (); }}실행 결과
167772895
객체의 인스턴스가 취해 지지만 다중 스레드 환경에있는 경우 싱글 톤 패턴이 아닌 여러 인스턴스가 발생합니다.
테스트 클래스를 실행하십시오
패키지 com.weishiyao.learn.day8.singleton.ep2; public class run {public static void main (String [] args) {Mythread T1 = new Mythread (); Mythread T2 = New Mythread (); Mythread T3 = New Mythread (); Mythread T4 = New Mythread (); 신화 t5 = new Mythread (); t1.start (); t2.start (); t3.start (); t4.start (); t5.Start (); }}실행 결과
980258163
1224717057
1851889404
188820504
1672864109
문제가 있기 때문에 문제를 해결해야합니다. 게으른 모드의 다중 스레드 솔루션 코드 :
첫 번째 솔루션은 가장 일반적으로 동기화 된 추가 및 동기화 된 추가 위치에 추가 할 수 있습니다.
첫 번째 메소드가 잠겨 있습니다
패키지 com.weishiyao.learn.day8.singleton.ep3; public class myobject {private static myobject myobject; private myObject () {} 동기화 된 public static myObject getInstance () {// 지연로드 try {if (myObject! = null) {// 객체 스레드를 만들기 전에 일부 준비를 시뮬레이션합니다. myObject = new myObject (); }} catch (InterruptedException e) {e.printstacktrace (); } return myObject; }}이 동기화 된 동기화 체계는 너무 비효율적이며 전체 메소드가 잠겨 있습니다.
두 번째 동기화 된 사용 체계
패키지 com.weishiyao.learn.day8.singleton.ep3; public class myobject {private static myobject myobject; private myObject () {} public static myObject getInstance () {// 지연로드 try {synchronized (myObject.class) {if (myObject! = null) {// 객체 스레드를 만들기 전에 일부 준비 작업을 시뮬레이션합니다. myObject = new myObject (); }}} catch (InterruptedException e) {e.printstacktrace (); } return myObject; }} 이 방법은 효율성이 매우 낮습니다. 이 방법의 모든 코드는 잠겨 있습니다. 키 코드 만 잠숙 필요 만하면됩니다. 세 번째 동기화 된 사용 계획
패키지 com.weishiyao.learn.day8.singleton.ep3;
공개 클래스 myObject {private static myObject myObject; private myObject () {} public static myObject getInstance () {// 지연로드 try {if (myObject! = null) {} else {// 객체 스레드를 만들기 전에 일부 준비를 시뮬레이션합니다. synchronized (myObject.class) {myObject = new myObject (); }}} catch (InterruptedException e) {e.printstacktrace (); } return myObject; }}이것은 최상의 솔루션 인 것 같지만 실행 한 후에는 실제로 비틀 거리가 아니라는 것을 알았습니다.
결과:
1224717057
971173439
1851889404
1224717057
1672864109
왜?
객체를 생성하는 진술이 잠겨 있지만 한 번만 한 번에만 생성을 완료 할 수 있습니다. 첫 번째 스레드가 객체 객체를 생성하기 위해 들어온 후에도 두 번째 스레드는 계속 만들 수 있습니다.
패키지 com.weishiyao.learn.day8.singleton.ep3; public class myobject {private static myobject myobject; private myObject () {} public static myObject getInstance () {// 지연로드 try {if (myObject! = null) {} else {// 객체 스레드를 만들기 전에 일부 준비를 시뮬레이션합니다. synchronized (myObject.class) {if (myObject == null) {myObject = new myObject (); }}}} catch (InterruptedException e) {e.printstacktrace (); } return myObject; }}싱글 톤을 보장하기 위해 자물쇠에 또 다른 판단을 추가하십시오. 이것은 DCL 이중 점검 메커니즘입니다
결과는 다음과 같습니다.
1224717057
1224717057
1224717057
1224717057
1224717057
3. 내장 정적 클래스를 사용하여 단일 케이스를 구현하십시오
메인 코드
패키지 com.weishiyao.learn.day8.singleton.ep4; public class myobject {// 내부 클래스 메소드 개인 정적 클래스 myobjecthandler {private static myObject myObject = new myObject (); } public myObject () {} public static myObject getInstance () {return myobjecthandler.myObject; }} 스레드 클래스 코드
package com.weishiyao.learn.day8.singleton.ep4; public class mythread는 스레드 {@override public void run () {system.out.println (myobject.getInstance (). hashcode ()); }} 클래스를 실행하십시오
패키지 com.weishiyao.learn.day8.singleton.ep4; public class run {public static void main (string [] args) {Mythread T1 = new Mythread (); Mythread T2 = New Mythread (); Mythread T3 = New Mythread (); Mythread T4 = New Mythread (); 신화 t5 = new Mythread (); t1.start (); t2.start (); t3.start (); t4.start (); t5.Start (); }}결과
1851889404
1851889404
1851889404
1851889404
1851889404
내부 정적 클래스를 통해 스레드 안전 싱글 톤 패턴이 얻어집니다.
IV. 싱글 톤 패턴을 직렬화하고 실질화합니다
내장형 정적 클래스는 스레드 안전 문제를 해결할 수 있지만 직렬화 된 객체를 만나면 기본 메소드를 사용하여 얻은 결과는 여전히 여러 경우입니다.
myObject 코드
패키지 com.weishiyao.learn.day8.singleton.ep5; import java.io.serializable; public class myobject emperments serializable { / ** * / private static final long serialversionuid = 888l; // 내부 클래스 메소드 개인 정적 클래스 myObjecthandler {private static myObject myObject = new myObject (); } public myObject () {} public static myObject getInstance () {return myobjecthandler.myObject; } // protected myObject readResolve () {// system.out.println ( "readresolve 메소드가 호출되었습니다!"); // return myobjecthandler.myObject; //}} 사업
package com.weishiyao.learn.day8.singleton.ep5; import java.io.file; import java.io.fileInputStream; import java.io.filenotfoundException; import java.io.fileoutputStream; import java.io.io exception; import java.io.io.ob.io.oba.io.oo.oo.oo.oo.oo.oo.oo.ooba.io class saveAndread {public static void main (String [] args) {try {myObject myObject = myObject.getInstance (); fileoutputStream fosref = new FileOutputStream (새 파일 ( "myObjectFile.txt")); ObjectOutputStream oosRef = 새로운 ObjectOutputStream (FOSREF); oosref.writeobject (myobject); oosref.close (); fosref.close (); System.out.println (myObject.hashCode ()); } catch (filenotfoundException e) {e.printstacktrace (); } catch (ioexception e) {e.printstacktrace (); } fileInputStream fisref; try {fisref = new FileInputStream (새 파일 ( "myObjectFile.txt")); ObjectInputStream iOsRef = 새로운 ObjectInputStream (fisref); myObject myObject = (myObject) iOsRef.readObject (); iosref.close (); fisref.close (); System.out.println (myObject.hashCode ()); } catch (filenotfoundException e) {e.printstacktrace (); } catch (ioexception e) {e.printstacktrace (); } catch (classNotFoundException e) {e.printstacktrace (); }}}결과
970928725
1099149023
두 개의 다른 해시 코드는 그것들이 같은 객체가 아님을 증명합니다. 솔루션, 다음 코드를 추가하십시오
보호 된 myObject readResolve () {system.out.println ( "readResolve 메소드가 호출되었습니다!"); myobjecthandler.myobject를 반환합니다. }사막화 중에 호출하면 동일한 대상을 얻을 수 있습니다
System.out.println (myObject.readResolve (). hashcode ());
결과
1255301379
readresolve 방법이 호출되었습니다!
1255301379
동일한 해시 코드는 동일한 객체가 얻어 졌음을 증명합니다.
5. 정적 코드 블록을 사용하여 단일 케이스를 구현하십시오
정적 코드 블록의 코드는 클래스를 사용할 때 이미 실행되므로 STATIC CODE FAST의 기능을 사용하여 간단한 이익 모드를 구현할 수 있습니다.
myObject 클래스
패키지 com.weishiyao.learn.day8.singleton.ep6; public class myobject {private static myobject instance = null; private myobject () {super (); } static {instance = new myObject (); } public static myObject getInstance () {return instance; }} 스레드 클래스
package com.weishiyao.learn.day8.singleton.ep6; public class mythread는 스레드 {@override public void run () {for (int i = 0; i <5; i ++) {system.out.println (myObject.getInstance (). hashcode ()); }}} 클래스를 실행하십시오
패키지 com.weishiyao.learn.day8.singleton.ep6; public class run {public static void main (String [] args) {Mythread T1 = new Mythread (); Mythread T2 = New Mythread (); Mythread T3 = New Mythread (); Mythread T4 = New Mythread (); 신화 t5 = new Mythread (); t1.start (); t2.start (); t3.start (); t4.start (); t5.Start (); }}실행 결과 :
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
스레드-안전 싱글 톤 패턴은 정적 코드 블록을 한 번만 실행하는 기능을 통해 성공적으로 얻습니다.
6. Enum Enum 데이터 유형을 사용하여 싱글 톤 모드를 구현합니다.
열거적 열거 및 정적 코드 블록의 특성은 유사합니다. 열거를 사용하는 경우 생성자는 자동으로 호출되며 싱글 톤 모드를 구현하는 데 사용될 수도 있습니다.
myObject 클래스
패키지 com.weishiyao.learn.day8.singleton.ep7; import java.sql.connection; import java.sql.drivermanager; import java.sql.sqlexception; public enum myObject {ConnectionActory; 개인 연결 연결; private myObject () {try {system.out.println ( "myObject의 구성이 불렸다"); 문자열 URL = "jdbc : mysql : //172.16.221.19 : 3306/wechat_1? useUnicode = true & characterEncoding = utf-8"; 문자열 이름 = "루트"; 문자열 암호 = "111111"; String drivername = "com.mysql.jdbc.driver"; class.forname (drivername); Connection = DriverManager.GetConnection (URL, 이름, 암호); } catch (classNotFoundException e) {e.printstacktrace (); } catch (sqlexception e) {e.printstacktrace (); }} public Connection getConnection () {반환 연결; }} 스레드 클래스
package com.weishiyao.learn.day8.singleton.ep7; public class mythread는 스레드 {@override public void run () {for (int i = 0; i <5; i ++) {system.out.println (myobject.connection.connectioncactory.getConnection (). hashcode (); }}} 클래스를 실행하십시오
패키지 com.weishiyao.learn.day8.singleton.ep7; public class run {public static void main (string [] args) {Mythread T1 = new Mythread (); Mythread T2 = New Mythread (); Mythread T3 = New Mythread (); Mythread T4 = New Mythread (); 신화 t5 = new Mythread (); t1.start (); t2.start (); t3.start (); t4.start (); t5.Start (); }}실행 결과
myObject 구조라고합니다
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
위의 쓰기 방법은 "단일 책임 원칙"을 위반하는 열거 클래스를 노출시킵니다. 클래스를 사용하여 열거를 마무리 할 수 있습니다.
패키지 com.weishiyao.learn.day8.singleton.ep8; import java.sql.connection; import java.sql.drivermanager; import java.sql.sqlexception; public class myObject {public enum myenumsingleton {ConnectionFactory; 개인 연결 연결; private myEnumsingleton () {try {system.out.println ( "myObject의 구성이 불렸다"); 문자열 URL = "jdbc : mysql : //172.16.221.19 : 3306/wechat_1? useUnicode = true & characterEncoding = utf-8"; 문자열 이름 = "루트"; 문자열 암호 = "111111"; String drivername = "com.mysql.jdbc.driver"; class.forname (drivername); Connection = DriverManager.GetConnection (URL, 이름, 암호); } catch (classNotFoundException e) {e.printstacktrace (); } catch (sqlexception e) {e.printstacktrace (); }} public Connection getConnection () {반환 연결; }} public static connection getConnection () {return myenumsingleton.connectionFactory.getConnection (); }} 스레드 코드를 변경하십시오
package com.weishiyao.learn.day8.singleton.ep8; public class mythread는 스레드 {@override public void run () {for (int i = 0; i <5; i ++) {system.out.println (myObject.getConnection (). hashcode ()); }}} 결과적으로 MyObject 구조가 호출됩니다
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
위의 내용은 단일 이익 모드를 멀티 스레딩과 결합 할 때 발생하는 다양한 상황과 솔루션을 요약하여 나중에 사용할 때 검토 할 수 있습니다.