개념:
Java의 싱글 톤 패턴은 일반적인 디자인 패턴입니다. 싱글 톤 패턴은 게으른 싱글 톤, 배고픈 싱글 톤 및 등록 된 싱글 톤의 세 가지 유형으로 나뉩니다.
싱글 톤 모드에는 다음과 같은 특성이 있습니다.
1. 싱글 톤 클래스에는 하나의 인스턴스 만있을 수 있습니다.
2. 싱글 톤 클래스는 고유 한 인스턴스를 만들어야합니다.
3. 싱글 톤 클래스는이 인스턴스를 다른 모든 객체에 제공해야합니다.
싱글 톤 패턴은 클래스에 하나의 인스턴스 만 있도록하고 자체적으로 인스턴스를 인스턴스화 하고이 인스턴스를 전체 시스템에 제공합니다. 컴퓨터 시스템에서 스레드 풀, 캐시, 로그 객체, 대화 상자, 프린터 및 그래픽 카드의 드라이버 객체는 종종 싱글 톤으로 설계됩니다. 이러한 응용 프로그램에는 리소스 관리자의 기능이 어느 정도 있습니다. 각 컴퓨터에는 여러 프린터가있을 수 있지만 동시에 프린터에 두 개의 인쇄 작업이 출력되는 것을 피하기 위해 하나의 프린터 스풀러 만 사용할 수 있습니다. 각 컴퓨터에는 여러 통신 포트가있을 수 있으며 시스템은 두 개의 요청에 의해 하나의 통신 포트가 동시에 호출되는 것을 피하기 위해 이러한 통신 포트를 중앙에서 관리해야합니다. 요컨대, 싱글 톤 모델을 선택하는 것은 일관되지 않은 상태를 피하고 정치적 강세를 피하는 것입니다.
다음은 두 가지 유형의 소개입니다 : 게으르고 배고픈
1. 즉시로드/배고픈 스타일
메소드를 호출하기 전에 인스턴스가 작성되었습니다.
PACKED COM.WEISHIYAO.LEARN.LEAR.SINGLETON.EP; public class myObject {//로드 NOW == evil mode private modect myObject = new myObject (); public myObject () {} public myObject () {} 공개 정적 myObject getInstance () {//이 코드의 불의가 없기 때문입니다. getInstance () 메소드가 동기화되지 않아 // 비 스레드-안전 문제가 발생할 수 있습니다. return myObject;}} 스레드 클래스를 만듭니다
package com.weishiyao.learn.lud.singleton.ep; public class mythread는 스레드 {@overridepublic void run () {system.out.println (myObject.getInstance (). hashcode ());}} 런 클래스를 만듭니다
PACKED COM.WEISHIYAO.LEARN.DAY.SINGLETON.EP; PUBLIC CLASS RUN {public static void Main (String [] args) {MythRead T = new Mythread (); Mythread T = New Mythread (); Mythread T = New Mythread (); T.start (); T.start (); T.start (); t.start ();}} 실행 결과
1 167772895
2 167772895
3 167772895
해시 코드는 동일한 값이므로 객체도 동일하다는 것을 의미합니다. 즉, 즉각적인 로딩 모드가 구현되었음을 의미합니다.
2. 게으른 하중/게으른
메소드가 호출 된 후 인스턴스가 생성됩니다. 구현 계획은 매개 변수가없는 생성자에 인스턴스화를 배치하여 메소드의 인스턴스가 메소드가 호출 될 때만 생성되는 것입니다. 암호:
package com.weishiyao.learn.day.singleton.ep; public class myObject {private static myObject myObject; private myObject () {} public static myObject getInstance () {// 지연로드 (myObject! = null) {myObject = new myObject ();}}}}}}. 스레드 클래스를 만듭니다
package com.weishiyao.learn.lud.singleton.ep; public class mythread는 스레드 {@overridepublic 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 ();}} 실행 결과
1 167772895
객체의 인스턴스가 취해 지지만 다중 스레드 환경에있는 경우 싱글 톤 패턴이 아닌 여러 인스턴스가 발생합니다.
테스트 클래스를 실행하십시오
PACKED COM.WEISHIYAO.LEARN.DAY.SINGLETON.EP; PUBLIC CLASS RUN {public static void main (String [] args) {mythread t = new Mythread (); mythread t = new Mythread (); new Mythread (); Mythread T = New Mythread (); mythread (); t.start (); t.start (); t.start (); t.start (); t.start (); t.start (); }} 실행 결과
1 980258163
2 1224717057
3 1851889404
4 188820504
5 1672864109
문제가 있기 때문에 문제를 해결해야합니다. 게으른 모드의 다중 스레드 솔루션 코드 :
첫 번째 솔루션은 가장 일반적으로 동기화 된 추가 및 동기화 된 추가 위치에 추가 할 수 있습니다.
첫 번째 메소드가 잠겨 있습니다
package com.weishiyao.learn.lud.singleton.ep; public class myObject {private static myObject myObject; private myObject () {} 동기화 된 public static myObject getInstance () {//로드가 지연됩니다. myObject = new myObject (); }} catch (InterruptedException e) {e.printstacktrace ();} return myObject;}}} 이 동기화 된 동기화 체계는 너무 비효율적이며 전체 메소드가 잠겨 있습니다.
두 번째 동기화 된 사용 체계
package com.weishiyao.learn.learn.day.singleton.ep; public class myObject {private static myObject myObject; private myObject () {} public static myObject getInstance () {// 지연로드 시도 {synchronized (myObject.class) {if (myObject! = null)} Thread.sleep (); myObject = new myObject ();}}} catch (InterruptedException e) {e.printstacktrace ();} return myObject;}} 이 방법은 효율성이 매우 낮습니다. 이 방법의 모든 코드는 잠겨 있습니다. 키 코드 만 잠숙 필요 만하면됩니다. 세 번째 동기화 된 사용 계획
package com.weishiyao.learn.day.singleton.ep; public class myObject {private static myObject myObject; private myObject () {} public static myObject getInstance () {// 지연을 지연시켜 {if (myObject! = null) {// 객체를 생성하기 전에 (myObject! = null) {) {myObrons (); {myObject = new myObject ();}}} catch (InterpruptedException e) {e.printstacktrace ();} return myObject;}} 이것은 최상의 솔루션 인 것 같지만 실행 한 후에는 실제로 비틀 거리가 아니라는 것을 알았습니다.
결과:
1 1224717057
2 971173439
3 1851889404
4 1224717057
5 1672864109
왜?
객체를 생성하는 진술이 잠겨 있지만 한 번만 한 번에만 생성을 완료 할 수 있습니다. 첫 번째 스레드가 객체 객체를 생성하기 위해 들어온 후에도 두 번째 스레드는 계속 만들 수 있습니다.
PACKED COM.Weishiyao.learn.Learn.singleton.ep; public class myObject {private static myObject MyObject; private myObject () {} public static myObject getInstance () {// 지연로드를 지연시켜 {myObject! = null) {// 객체를 생성하기 전에 일부 준비 작업 (). (myObject.class) {if (myObject == null) {myObject = new myObject ();}}} catch (InterruptedException e) {e.printstacktrace ();} myObject;}}}. 싱글 톤을 보장하기 위해 자물쇠에 또 다른 판단을 추가하십시오. 이것은 DCL 이중 점검 메커니즘입니다
결과는 다음과 같습니다.
1 1224717057
2 1224717057
3 1224717057
4 1224717057
5 1224717057
3. 내장 정적 클래스를 사용하여 단일 케이스를 구현하십시오
메인 코드
package com.weishiyao.learn.day.singleton.ep; public class myobject {// 내부 클래스 메소드 개인 정적 클래스 myobjecthandler {private static myobject = new myobject ();} public myObject () {} public static myObject getInstance () {return myObjecthAndler.}}. 스레드 클래스 코드
package com.weishiyao.learn.lud.singleton.ep; public class mythread는 스레드 {@overridepublic void run () {system.out.println (myObject.getInstance (). hashcode ());}} 클래스를 실행하십시오
PACKED COM.WEISHIYAO.LEARN.DAY.SINGLETON.EP; PUBLIC CLASS RUN {public static void main (String [] args) {mythread t = new Mythread (); mythread t = new Mythread (); new Mythread (); Mythread T = New Mythread (); mythread (); t.start (); t.start (); t.start (); t.start (); t.start (); t.start (); }} 결과
1851889404
1851889404
1851889404
1851889404
1851889404
내부 정적 클래스를 통해 스레드 안전 싱글 톤 패턴이 얻어집니다.
IV. 싱글 톤 패턴을 직렬화하고 실질화합니다
내장형 정적 클래스는 스레드 안전 문제를 해결할 수 있지만 직렬화 된 객체를 만나면 기본 메소드를 사용하여 얻은 결과는 여전히 여러 경우입니다.
myObject 코드
PACKED COM.WEISHIYAO.LEAR8.SINGLETON.EP5; import java.io.serializable; 공개 클래스 myObject 구현 시리얼이 가능 {/****/private static final long serialversionuid = 888l; // 내부 클래스 방법 개인 클래스 myobjecthandler (private myobjep republe retatic myObjep myObjep MyObjep MyObject MyObject). {{} public static myObject getInstance () {return myObjecthandler.myObject;} // protected myObject readResolve () {// system.out.println ( "readresolve 메소드가 호출되었습니다!"); // return myobjecthandler.myObject; //}}}}}}}}}}} 사업
package com.weishiyao.learn.day.singleton.ep; import java.io.file; import java.io.fileinputstream; import java.io.filenotfoundException; import java.io.fileoutputStream; import java.io.ioexception; import java.io.objectinprantStream; saveAndread {public static void main (string [] args) {try {myObject myObject = myObject.getInstance (); fileoutputStream fosref = new FileOutputStream ( "myObjectFile.txt"); ObjectOutoutPutStream oosref = new ObjectOutputStream (fosref); oosref.writeobject (myObject); oosref.close (); fosref.close (); system.out.println (myobject.hashcode ());} catch (filenotfoundException e) {e.printstacktrace ();} catch (ioexection e) {e.printstacktrace ();} fileInputStream fisref; try {fisref = new FileInputStream (새 파일 ( "myObjectFile.txt")); ObjectInputStream iOsRef = new 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 (classnotcection e)) {e.printstacktrace ();}}} 결과
1 970928725
2 1099149023
두 개의 다른 해시 코드는 그것들이 같은 객체가 아님을 증명합니다. 솔루션, 다음 코드를 추가하십시오
보호 된 myObject readResolve () {system.out.println ( "readResolve 메소드가 호출되었습니다!"); return myobjecthandler.myObject;}} 사막화 중에 호출하면 동일한 대상을 얻을 수 있습니다
System.out.println (myObject.readResolve (). hashcode ());
결과
1 1255301379
2 readResolve 방법이 호출되었습니다!
3 1255301379
동일한 해시 코드는 동일한 객체가 얻어 졌음을 증명합니다.
5. 정적 코드 블록을 사용하여 단일 케이스를 구현하십시오
정적 코드 블록의 코드는 클래스를 사용할 때 이미 실행되므로 STATIC CODE FAST의 기능을 사용하여 간단한 이익 모드를 구현할 수 있습니다.
myObject 클래스
package com.weishiyao.learn.lud.singleton.ep; public class myObject {private static myObject instance = null; private myObject () {super ();} static {instation = new myObject ();} public static myObject getInstance () {return indistance;}} 스레드 클래스
package com.weishiyao.learn.lud.singleton.ep; public class mythread는 스레드 {@overridepublic void run () {for (int i =; i <; i ++) {system.out.println (myObject.getInstance (). hashcode ());}}}}}}}}}} { 클래스를 실행하십시오
PACKED COM.WEISHIYAO.LEARN.DAY.SINGLETON.EP; PUBLIC CLASS RUN {public static void main (String [] args) {mythread t = new Mythread (); mythread t = new Mythread (); new Mythread (); Mythread T = New Mythread (); mythread (); t.start (); t.start (); t.start (); t.start (); t.start (); t.start (); }} 실행 결과 :
1 1678885403
2 1678885403
3 1678885403
4 1678885403
5 1678885403
6 1678885403
7 1678885403
8 1678885403
9 1678885403
10 1678885403
11 1678885403
12 1678885403
13 1678885403
14 1678885403
15 1678885403
16 1678885403
17 1678885403
18 1678885403
19 1678885403
20 1678885403
21 1678885403
22 1678885403
23 1678885403
24 1678885403
25 1678885403
스레드-안전 싱글 톤 패턴은 정적 코드 블록을 한 번만 실행하는 기능을 통해 성공적으로 얻습니다.
6. Enum Enum 데이터 유형을 사용하여 싱글 톤 모드를 구현합니다.
열거적 열거 및 정적 코드 블록의 특성은 유사합니다. 열거를 사용하는 경우 생성자는 자동으로 호출되며 싱글 톤 모드를 구현하는 데 사용될 수도 있습니다.
myObject 클래스
package com.weishiyao.learn.day.singleton.ep; import java.sql.connection; import java.sql.drivermanager; import java.sql.sqlexception; public enum myObject {ConnectionFactory; private myObject () {systing.out.println (myObject.out.println); "jdbc : mysql : // ... :/wechat_? useUnicode = true & characterEncoding = utf-"; String name = "rit password"; String password = "; String driverName ="com.mysql.jdbc.driver "; class.forname (driverManager.getConnection) {e.printstacktrace ();} catch (sqlexception e) {e.printstacktrace ();}} public connection getConnection () {return connection;}} 스레드 클래스
package com.weishiyao.learn.day.singleton.ep; public class mythread는 스레드 {@overridepublic void run () {for (int i =; i <; i ++) {system.out.println (myObject.ConnectionFactory.getConnection ())}}}}}}}}}} 클래스를 실행하십시오
package com.weishiyao.learn.day.singleton.ep; public class run {public static void main (String [] args) {mythread t = new Mythread (); mythread t = new Mythread (); mythread (); mythread t = new Mythread (); mythread (); t.start (); t.start (); t.start (); t.start (); t.start (); t.start (); }} 실행 결과
1 myObject 구조가 호출되었습니다
2 56823666
3 56823666
4 56823666
5 56823666
6 56823666
7 56823666
8 56823666
9 56823666
10 56823666
11 56823666
12 56823666
13 56823666
14 56823666
15 56823666
16 56823666
17 56823666
18 56823666
19 56823666
20 56823666
21 56823666
22 56823666
23 56823666
24 56823666
25 56823666
26 56823666
위의 쓰기 방법은 "단일 책임 원칙"을 위반하는 열거 클래스를 노출시킵니다. 클래스를 사용하여 열거를 마무리 할 수 있습니다.
package com.weishiyao.learn.day.singleton.ep; import java.sql.connection; import java.sql.drivermanager; import java.sql.sqlexception; public class myobject {public enum myenumsingleton {connection -connection; private myenumsinginginginging 싱턴 () {system.oug. MyObject는 "); String url ="JDBC : mysql : // ... :/wechat_? useUnicode = true & characterEncoding = utf- "; string name ="root "; String password =" "; String driverName ="com.mysql.jdbc.driver "; class.forname (drivermanager.getmanager. 암호);} catch (classNotFoundException e) {e.printstacktrace ();} catch (sqlexception e) {e.printstacktrace ();}} public connection getConnection () {return connection;}} public static connection getConnection () {return myenumsingleton.connection factory.get}) 스레드 코드를 변경하십시오
package com.weishiyao.learn.lud.singleton.ep; public class mythread는 스레드 {@overridepublic void run () {for (int i =; i <; i ++) {system.out.println (myobject.getConnection (). hashcode ());}}}}}}}}}} { 결과
1 myObject 구조가 호출되었습니다
2 1948356121
3 1948356121
4 1948356121
5 1948356121
6 1948356121
7 1948356121
8 1948356121
9 1948356121
10 1948356121
11 1948356121
12 1948356121
13 1948356121
14 1948356121
15 1948356121
16 1948356121
17 1948356121
18 1948356121
19 1948356121
20 1948356121
21 1948356121
22 1948356121
23 1948356121
24 1948356121
25 1948356121
26 1948356121
위의 내용은 단일 이익 모드를 멀티 스레딩과 결합 할 때 발생하는 다양한 상황과 솔루션을 요약하여 나중에 사용할 때 검토 할 수 있습니다.