コンセプト:
JavaのSingletonパターンは、一般的なデザインパターンです。シングルトンパターンは、レイジーシングルトン、ハングリーシングルトン、登録されたシングルトンの3つのタイプに分かれています。
Singletonモードには次の特性があります。
1.シングルトンクラスには1つのインスタンスしかありません。
2。シングルトンクラスは、独自のユニークなインスタンスを作成する必要があります。
3. Singletonクラスは、他のすべてのオブジェクトにこのインスタンスを提供する必要があります。
Singleton Patternは、クラスに1つのインスタンスしかないことを保証し、それ自体をインスタンス化し、このインスタンスをシステム全体に提供します。コンピューターシステムでは、スレッドプール、キャッシュ、ログオブジェクト、ダイアログボックス、プリンター、グラフィックカード用のドライバーオブジェクトは、多くの場合、シングルトンとして設計されています。これらのアプリケーションには、多かれ少なかれリソースマネージャーの機能があります。各コンピューターには複数のプリンターを使用できますが、プリンタースプーラーが1つだけ使用できるのは、2つの印刷ジョブが同時に出力されないようにすることができます。各コンピューターにはいくつかの通信ポートがあり、システムはこれらの通信ポートを中央に管理して、1つの通信ポートが2つのリクエストによって同時に呼び出されないようにする必要があります。要するに、シングルトンモデルを選択することは、一貫性のない状態を避け、政治的な強気を避けることです。
ここに2種類の紹介があります:怠zyと空腹
1.すぐにロード/空腹のスタイル
メソッドを呼び出す前に、インスタンスが作成されました、コード:
パッケージcom.weishiyao.learn.day.singleton.ep; public class myobject {// loading now == evil mode private static myobject = new Myobject(); private myobject(){} public static myobject getInstance(){// getInstance()メソッドは同期していない//スレッドクラスを作成します
パッケージcom.weishiyao.learn.day.singleton.ep; public class mythread extends thread {@overridepublic void run(){system.out.println(myobject.getInstance()。hashcode();}}}}実行クラスを作成します
パッケージ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(); t.start();}}実行結果
1 167772895
2 167772895
3 167772895
ハッシュコードは同じ値です。つまり、オブジェクトも同じであることを意味します。つまり、インスタントロードモードが実装されています。
2。怠zyなロード/怠zy
インスタンスは、メソッドが呼び出された後に作成されます。実装計画は、オブジェクトのインスタンスがメソッドが呼び出された場合にのみ作成されるように、パラメーターのないコンストラクターにインスタンス化することです。コード:
パッケージcom.weishiyao.learn.day.singleton.ep; public class myobject {private static myobject myobject; private myobject(){} public static myobject getInstance(){//遅延ロードif(myobject!= null){} reter {} return {new myobject;};}スレッドクラスを作成します
パッケージcom.weishiyao.learn.day.singleton.ep; public class mythread extends thread {@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
オブジェクトのインスタンスは撮影されますが、マルチスレッド環境にある場合、複数のインスタンスが発生しますが、これはシングルトンパターンではありません。
テストクラスを実行します
パッケージ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(); mythread t = new mythread(); mythread t = new mythread(); t.start(); t.start(); t.start(); t.start(); t.start(); t.start(); }}実行結果
1 980258163
2 1224717057
3 1851889404
4 188820504
5 1672864109
問題があるので、問題を解決する必要があります。レイジーモードのマルチスレッドソリューション、コード:
最も一般的には、最初のソリューションは同期を追加し、同期して異なる位置に追加できます
最初の方法はロックされます
パッケージcom.weishiyao.learn.day.singleton.ep; public class myobject {private static myobject myobject; private myobject(){}同期されたpublic static myobject getInstance(){//遅延ロードtry {if(myobject!= null){} else {} semulate shimulate semulate shimulate shimulate shimulate shimulate shimulate shimulate myobject = new Myobject(); }} catch(arturnedexception e){e.printstacktrace();} return myobject;}}}この同期化された同期スキームは、効率が強すぎて、メソッド全体がロックされています
2番目の同期使用スキーム
パッケージcom.weishiyao.learn.day.singleton.ep; public class myobject {private static myobject myobject; private myobject(){} public static myobject getInstance(){// synchronized(myobject.class){if(myobject.class){if(myobject.class){null){} ximulate simulate prepinate thread.sleep(); myobject = new Myobject();}}} catch(arturnedexception e){e.printstacktrace();} return myobject;}}}この方法も非常に低い効率です。メソッド内のすべてのコードがロックされています。キーコードをロックするだけです。 3番目の同期使用計画
パッケージcom.weishiyao.learn.day.singleton.ep; public class myobject {private static myobject myobject; private myobject(){} public static myobject getInstance(){//遅延ロード{// if(myobject!= null){} beghimed synch.shook.shook.seprook() {myobject = new Myobject();}}} catch(arternedexception e){e.printstacktrace();} return myobject;}}これは最良の解決策のようですが、それを実行した後、私はそれが実際には非スレッドセーフであることがわかりました
結果:
1 1224717057
2 971173439
3 1851889404
4 1224717057
5 1672864109
なぜ?
オブジェクトを作成するステートメントはロックされていますが、最初のスレッドがオブジェクトオブジェクトを作成するために作成された後、1つのスレッドのみが作成を完了することができますが、2番目のスレッドは作成され続けることができます。
パッケージcom.weishiyao.learn.day.singleton.ep; public class myobject {private static myobject myobject; private myobject(){} public static myobject getInstance(){// Delay Loading try {if(myobject!= null){} beghimed synch.s sooks shook(// syprent(// syprent); {if(myobject == null){myobject = new Myobject();}}}} catch(arternedexception e){e.printstacktrace();} return myobject;}}}シングルトンを確保するために、ロックに別の判断を追加するだけです。これはDCLの再チェックメカニズムです
結果は次のとおりです。
1 1224717057
2 1224717057
3 1224717057
4 1224717057
5 1224717057
3.組み込みの静的クラスを使用して、単一のケースを実装します
メインコード
パッケージcom.weishiyao.learn.day.singleton.ep; public class myobject {// inner class method private static class myobjecthandler {private static myobject = new Myobject();} public myobject(){} public static myobject getInstance(){return byobjecthandl.myobject;}スレッドクラスコード
パッケージcom.weishiyao.learn.day.singleton.ep; public class mythread extends thread {@overridepublic void run(){system.out.println(myobject.getInstance()。hashcode();}}}}クラスを実行します
パッケージ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(); mythread t = new mythread(); mythread t = new mythread(); t.start(); t.start(); t.start(); t.start(); t.start(); t.start(); }}結果
1851889404
1851889404
1851889404
1851889404
1851889404
内部静的クラスを通じて、スレッドセーフシングルトンパターンが取得されます
IV。シングルトンのパターンをシリアル化して脱皮化します
組み込みの静的クラスは、スレッドの安全性の問題を実現できますが、シリアル化されたオブジェクトが発生した場合、デフォルトメソッドを使用して取得した結果は依然として複数のケースです。
myobjectコード
パッケージcom.weishiyao.learn.day8.singleton.ep5; import java.io.serializable; public class myobjectはシリアル化可能{/****/private static long serialversionuid = 888l; //内部クラスの方法私的静積筋筋by(Private Static Class Myobject = fublic myobject = private static Class myobject = public myobject = public myobject = public myobject = fubl static myobject getInstance(){return myobjecthandler.myobject;} // protected myobject readresolve(){// system.out.println( "readResolveメソッドは呼び出されました!"); // myobjecthandler.myobject; //}}}}仕事
パッケージ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.objectinputinputtrerm; saveandread {public static void main(string [] args){try {myobject myobject = myobject.getInstance(); fileoutputStream fosref = new fileoutputStream(new file( "myobjectfile.txt"); objectoutputStream oosRef = new ObjectOutputStream(fosref); oosref.writeobject(myobject); oosref.close(); fosref.close(); system.out.println(myobject.hashcode());} catch(filenotfoundexception e){e.printstrace();} catch(ioexction e) {e.printstacktrace();} fileinputStream fisref; try {fisref = new fileinputStream(new file( "MyobjectFile.txt")); objectInputStream iOSREF = new objectInputStream(fisref); myobject myobject =(myobject)(myobject) iOsref.ReadObject(); iOSREF.CLOSE(); fisref.close(); system.out.println(myobject.hashcode());} catch(filenotStacktrace(){e.printstacktrace();} catch(ioexception e){e.printstacktrace();} catch();} catch(); {e.printstacktrace();}}}結果
1 970928725
2 1099149023
2つの異なるハッシュコードは、それらが同じオブジェクトではないことを証明しています。解決策、次のコードを追加します
保護されたmyobject readResolve(){system.out.println( "readResolveメソッドが呼び出されました!"); return myobjecthandler.myobject;}脱介入中に呼び出されると、同じオブジェクトを取得できます
system.out.println(myobject.readResolve()。hashcode());
結果
1 1255301379
2 ReadResolveメソッドが呼び出されました!
3 1255301379
同じハッシュコードは、同じオブジェクトが取得されることを証明します
5.静的コードブロックを使用して、単一のケースを実装します
静的コードブロックのコードは、クラスを使用するときに既に実行されているため、静的コードの機能を使用して、単純な利益モードを実装できます。
myobjectクラス
パッケージcom.weishiyao.learn.day.singleton.ep; public class myobject {private static myobject instance = null; private myobject(){super();} static {instance = new Myobject();} public static myobject getInstance(){return inst;}}}}スレッドクラス
パッケージcom.weishiyao.learn.day.singleton.ep; public class mythread extends thread {@overridepublic void run(){for(int i =; i <; i ++){system.out.println(myobject.getinstance()。hashcode();}}}}}クラスを実行します
パッケージ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(); mythread t = new mythread(); mythread t = new 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
スレッドセーフシングルトンパターンは、静的コードブロックを1回だけ実行する機能によって正常に取得されます。
6.列挙列挙データ型を使用して、シングルトンモードを実装する
Enum Enumと静的コードブロックの特性は類似しています。 enumsを使用する場合、コンストラクターは自動的に呼び出され、Singletonモードを実装するためにも使用できます。
myobjectクラス
パッケージcom.weishiyao.learn.day.singleton.ep; Import java.sql.connection; Import java.sql.drivermanager; Import java.sql.sqlecception; public enum myobject {connectionfactory; private connections connection; private connection; private myobject() "JDBC:mysql:// ...:/wechat_?useunicode = true&charatereCoding = utf-"; string name = "root"; string password = ""; string drivername = "com.mysql.jdbc.driver"; class.forname(drivername); connection = drivermanager.getnectonecnection. (classNotFoundException e){e.printstacktrace();} catch(sqlexception e){e.printstacktrace();}} public connection getConnection(){return connection;}}スレッドクラス
パッケージcom.weishiyao.learn.day.singleton.ep; public class mythread extends thread {@overridepublic void run(){for(int i =; i <; i ++){system.out.println(myobject.connectionfactory.getConnection()。クラスを実行します
パッケージ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(); mythread t = new mythread(); mythread t = new 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
上記の執筆方法は、「単一の責任原則」に違反する列挙クラスを公開します。クラスを使用して列挙をラップできます。
パッケージcom.weishiyao.learn.day.singleton.ep; Import java.sql.connection; Import java.sql.drivermanager; Import java.sql.sqlecception; public class myobject {public enum myenumsingletonton {connectionefactory; private conteals; private myenumsedletonletonletonletonletonletonletonletonletonletone( myobjectは "); string url =" jdbc:mysql:// ...:/wechat_?useunicode = true&charatereCoding = utf- "; string name =" root "; string password =" "; string drivername =" com.mysql.jdbc.driver "; class = drivername(drivername);パスワード);} catch(classNotFoundException e){e.printstacktrace();} catch(sqlexception e){e.printstacktrace();}} public connection getConnection(){return connection;}} public static connection getConnection(){return MyenumsIndingleton.ConnectionLectionFectoryFactoryFactoryFactoryFactoryFactoryFactoryFactoryFectoryFectoryスレッドコードを変更します
パッケージcom.weishiyao.learn.day.singleton.ep; public class mythread extends thread {@overridepublic void run(){for(int i =; i <; i ++){system.out.print.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
上記は、シングルインテストモードとマルチスレッドを組み合わせるときに遭遇するさまざまな状況とソリューションをまとめたもので、後で使用するとレビューできます。