konsep:
Pola singleton di java adalah pola desain yang umum. Pola singleton dibagi menjadi tiga jenis: Lazy Singleton, Hungry Singleton, dan terdaftar Singleton.
Mode singleton memiliki karakteristik berikut:
1. Hanya ada satu contoh di kelas singleton.
2. Kelas Singleton harus membuat contoh uniknya sendiri.
3. Kelas Singleton harus memberikan contoh ini kepada semua objek lain.
Pola Singleton memastikan bahwa suatu kelas hanya memiliki satu contoh, dan membuat instansi itu sendiri dan memberikan contoh ini ke seluruh sistem. Dalam sistem komputer, objek driver untuk kumpulan utas, cache, objek log, kotak dialog, printer, dan kartu grafis sering dirancang sebagai singleton. Aplikasi ini memiliki lebih atau kurang fungsionalitas manajer sumber daya. Setiap komputer dapat memiliki beberapa printer, tetapi hanya satu spooler printer yang dapat tersedia untuk menghindari dua pekerjaan cetak yang menghasilkan printer pada saat yang sama. Setiap komputer dapat memiliki beberapa port komunikasi, dan sistem harus mengelola port komunikasi ini secara terpusat untuk menghindari satu port komunikasi yang disebut secara bersamaan dengan dua permintaan. Singkatnya, memilih model singleton adalah untuk menghindari negara -negara yang tidak konsisten dan menghindari bullish politik.
Berikut adalah dua jenis perkenalan: malas dan lapar
1. Muat segera/gaya lapar
Sebelum memanggil metode, instance telah dibuat, kode:
package com.weishiyao.learn.day.singleton.ep;public class MyObject {// Loading now==Evil mode private static MyObject myObject = new MyObject();private MyObject() {}public static MyObject getInstance() {// This code version is loading now// The disadvantage of this version of the code is that there cannot be other instance variables// Because the Metode getInstance () tidak disinkronkan // Oleh karena itu, masalah non-thread-aman dapat terjadi pengembalian myObject;}} Buat kelas utas
Paket com.weishiyao.learn.day.singleton.ep; kelas publik mythread memperluas utas {@overridepublic void run () {System.out.println (myobject.getInstance (). HashCode ());}} Buat Kelas Jalankan
Paket com.weishiyao.learn.day.singleton.ep; kelas publik run {public static void main (string [] args) {mythread t = new mythread (); mythread t = t.start (); mythread t = mythread baru (); t.start (); t.start (); mythread t = mythread (); t.start (); t.start (); mythread t = mythread (); t.start (); t.start (); t.start ();}} Hasil berjalan
1 167772895
2 167772895
3 167772895
HashCode adalah nilai yang sama, yang berarti bahwa objek juga sama, yang berarti bahwa mode pemuatan instan diimplementasikan.
2. Pemuatan malas/malas
Contoh akan dibuat setelah metode dipanggil. Rencana implementasi dapat menempatkan instantiasi ke dalam konstruktor tanpa parameter, sehingga instance dari objek akan dibuat hanya ketika metode dipanggil. Kode:
Paket com.weishiyao.learn.day.singleton.ep; kelas publik myobject {private static myobject myObject; private myobject () {} public static myobject getInstance () {// tunda memuat if (myObject! = null) {} else {myObject = myobject = my kembalikan ife () {{myObject = myobject = my retrect (my ickare () {{myObject = my ickary ucapan saya () {myObject = my return my rams kembali () {myObject = my uchying (myOblEns ower (MyObject! Buat kelas utas
Paket com.weishiyao.learn.day.singleton.ep; kelas publik mythread memperluas utas {@overridepublic void run () {System.out.println (myobject.getInstance (). HashCode ());}} Buat Kelas Jalankan
Paket com.weishiyao.learn.day8.singleton.ep2; kelas publik run {public static void main (string [] args) {mythread t1 = mythread baru (); t1.start ();}} Hasil berjalan
1 167772895
Meskipun sebuah instance dari suatu objek diambil, jika berada di lingkungan multi-threaded, beberapa instance akan terjadi, yang bukan pola singleton
Jalankan kelas tes
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 t = new MyThread();MyThread t = new MyThread();MyThread t = new MyThread (); t.start (); t.start (); t.start (); t.start (); t.start (); t.start (); }} Hasil berjalan
1 980258163
2 1224717057
3 1851889404
4 188820504
5 1672864109
Karena ada masalah, kita perlu menyelesaikan masalah. Solusi multithreaded dalam mode malas, kode:
Solusi pertama, paling umum, tambahkan disinkronkan, dan disinkronkan dapat ditambahkan ke posisi yang berbeda
Metode pertama mengunci
Paket com.weishiyao.learn.day.singleton.ep; kelas publik myobject {private static static myobject; private myobject () {} disinkronkan public myobject getInstance () {// tunda cobalah {if (myObject! = null) {} lain {/ // tunda cobalah {if (myObject! myObject = myObject baru (); }} catch (InterruptedException e) {E.PrintStackTrace ();} return myObject;}} Skema sinkronisasi yang disinkronkan ini menghasilkan terlalu tidak efisien dan seluruh metode terkunci
Skema penggunaan yang disinkronkan kedua
Paket com.weishiyao.learn.day.singleton.ep; kelas publik myObject {private static myobject myObject; private myobject () {} public static myObject getInstance () {// tunda muat coba {sinkronisasi (myObject.class) {if (myObject! Thread.sleep (); myobject = new myobject ();}}} catch (interruptedexception e) {e.printstacktrace ();} return myObject;}} Metode ini juga sangat efisiensi rendah. Semua kode dalam metode ini dikunci. Anda hanya perlu mengunci kode kunci. Rencana Penggunaan Sinkronisasi Ketiga
Paket com.weishiyao.learn.day.singleton.ep; kelas publik myobject {private static myobject myObject; private myobject () {} public static myobject getInstance () {// tunda memuat {if (myObject! = null) {} {// beberapa persiapan {if (if (myObject! = null) {{{// (Myobject.class) {myobject = new myobject ();}}} catch (interruptedException e) {e.printstacktrace ();} return myobject;}} Ini tampaknya menjadi solusi terbaik, tetapi setelah menjalankannya, saya menemukan bahwa itu sebenarnya tidak aman
hasil:
1 1224717057
2 971173439
3 1851889404
4 1224717057
5 1672864109
Mengapa?
Meskipun pernyataan yang membuat objek terkunci, hanya satu utas yang dapat menyelesaikan kreasi sekaligus, setelah utas pertama masuk untuk membuat objek objek, utas kedua masih dapat terus membuatnya, karena kami hanya mengunci pernyataan pembuatan, solusi masalah ini ini
Paket com.weishiyao.learn.day.singleton.ep; kelas publik myobject {private static myobject myObject; private myobject () {} public static myobject getInstance () {// tunda memuat {if (myObject! = null) {} {// simulation beberapa persiapan {if (myObject! = null) {{{{{// simulasi beberapa persiapan. (Myobject.class) {if (myobject == null) {myobject = new myobject ();}}}} catch (interruptedexception e) {e.printstacktrace ();} return myObject;}} Cukup tambahkan penilaian lain ke kunci untuk memastikan singleton. Ini adalah mekanisme pemeriksaan ganda DCL
Hasilnya adalah sebagai berikut:
1 1224717057
2 1224717057
3 1224717057
4 1224717057
5 1224717057
3. Gunakan kelas statis bawaan untuk mengimplementasikan kasus tunggal
Kode utama
package com.weishiyao.learn.day.singleton.ep;public class MyObject {// Inner class method private static class MyObjectHandler {private static MyObject myObject = new MyObject();}public MyObject() {}public static MyObject getInstance() {return MyObjectHandler.myObject;}} Kode kelas utas
Paket com.weishiyao.learn.day.singleton.ep; kelas publik mythread memperluas utas {@overridepublic void run () {System.out.println (myobject.getInstance (). HashCode ());}} Jalankan kelas
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 t = new MyThread();MyThread t = new MyThread();MyThread t = new MyThread (); t.start (); t.start (); t.start (); t.start (); t.start (); t.start (); }} hasil
1851889404
1851889404
1851889404
1851889404
1851889404
Melalui kelas statis internal, pola singleton yang aman dan aman diperoleh
Iv. Serialize dan deserialize pola singleton
Kelas statis bawaan dapat mencapai masalah keamanan utas, tetapi jika Anda menemukan objek serial, hasil yang diperoleh dengan menggunakan metode default masih banyak kasus.
Kode myObject
package com.weishiyao.learn.day8.singleton.ep5;import java.io.Serializable;public class MyObject implements Serializable {/*** */private static final long serialVersionUID = 888L;// Internal class method private static class MyObjectHandler {private static MyObject myObject = new MyObject();}public MyObject() {} public static myobject getInstance () {return myobjecthandler.myobject;} // terlindungi myobject readResolve () {// system.out.println ("Metode readResolve dipanggil!"); // return myobjecthandler.myobject; //}}}}}}}}}}}}}}} Bisnis
Paket com.weishiyao.learn.day.singleton.ep; impor java.io.file; impor java.io.fileInputStream; java.io.ObjectOutputStream;public class 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.printstackrace ();} {e.printstackrace ();} {e.printstackrace ();} {e.printstackrace ();} {e.printstack (); {E.PrintStackTrace ();} FileInputStream fisref; coba {fisref = FileInputStream baru (file baru ("myobjectfile.txt")); objekinputStream 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.printscrace (); {E.PrintStackTrace ();}}} hasil
1 970928725
2 1099149023
Dua kode hash yang berbeda membuktikan bahwa mereka bukan objek yang sama. Solusi, tambahkan kode berikut
Dilindungi myObject readResolve () {System.out.println ("Metode ReadResolve dipanggil!"); return myobjecthandler.myobject;} Dipanggil selama deserialisasi, Anda bisa mendapatkan objek yang sama
System.out.println (myobject.readResolve (). HashCode ());
hasil
1 1255301379
2 Metode ReadResolve dipanggil!
3 1255301379
Kode hash yang sama membuktikan bahwa objek yang sama diperoleh
5. Gunakan blok kode statis untuk mengimplementasikan kasus tunggal
Kode dalam blok kode statis sudah dieksekusi saat menggunakan kelas, sehingga fitur kode statis cepat dapat digunakan untuk mengimplementasikan mode laba sederhana.
Kelas myObject
Paket com.weishiyao.learn.day.singleton.ep; kelas publik myobject {private static myobject instance = null; private myobject () {super ();} static {instance = new myobject ();} public static myObject getInstance () {return;}} new MyObject (); Kelas utas
Paket com.weishiyao.learn.day.singleton.ep; kelas publik mythread memperluas utas {@Overridepublic void run () {for (int i =; i <; i ++) {System.out.println (myObject.getInstance (). HASHCODE ();}}}}}; Jalankan kelas
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 t = new MyThread();MyThread t = new MyThread();MyThread t = new MyThread (); t.start (); t.start (); t.start (); t.start (); t.start (); t.start (); }} Hasil Menjalankan:
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
Pola singleton yang aman-aman berhasil diperoleh melalui fitur hanya mengeksekusi blok kode statis sekali.
6. Gunakan tipe data enum enum untuk mengimplementasikan mode singleton
Karakteristik enum enum dan blok kode statis serupa. Saat menggunakan enum, konstruktor akan dipanggil secara otomatis dan juga dapat digunakan untuk mengimplementasikan mode singleton.
Kelas myObject
Paket com.weishiyao.learn.day.singleton.ep; impor java.sql.connection; import java.sql.driverManager; impor java.sql.sqlexception; public myObject {connectionFactory; koneksi pribadi; private myobject () {cobalah {cobalah {oM.OUT {connectionFactory; connection connection; private myobject () {cobalah {cobalah {oM.OUT {connection {connection; "JDBC: mysql: // ...:/weChat_? UseUnicode = true & characterencoding = utf-"; string name = "root"; string password = ""; string drivername = "com.mysql.jdbc.driver"; class.forname (drivername); connection = drivernfex.goncon. e) {e.printstacktrace ();} catch (sqlexception e) {e.printstacktrace ();}} koneksi publik getConnection () {return connection;}} Kelas utas
Paket com.weishiyao.learn.day.singleton.ep; kelas publik mythread memperluas utas {@Overridepublic void run () {for (int i =; i <; i ++) {System.out.println (myObject.connectionFactory.getConnection (). HasHcode () ()) (). Jalankan kelas
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 t = new MyThread();MyThread t = new MyThread();MyThread t = new MyThread (); t.start (); t.start (); t.start (); t.start (); t.start (); t.start (); }} Hasil berjalan
1 MyObject Construct dipanggil
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
Metode penulisan di atas memperlihatkan kelas enumerasi, yang melanggar "prinsip tanggung jawab tunggal". Anda dapat menggunakan kelas untuk membungkus enumerasi.
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 {connectionFactory;private Connection connection;private MyEnumSingleton() {try {System.out.println ("Konstruksi myObject disebut"); string url = "jdbc: mysql: // ...:/weChat_? UseUnicode = true & characterencoding = utf-"; string name = "root"; string kata sandi = ""; string drivername = "com.mysql.jd.jd.jdbc.jdc.jdc.driver. DriverManager.getConnection (url, nama, kata sandi);} catch (classnotfoundException e) {e.printstacktrace ();} catch (sqlexception e) {e.printstacktrace ();}} public connection getConnection () {return connection;}} public connection static getConneksi () {return connection;}} public connection static getConnon Myenumsingleton.connectionfactory.getConnection ();}} Ubah kode utas
Paket com.weishiyao.learn.day.singleton.ep; kelas publik mythread memperluas utas {@Overridepublic void run () {for (int i =; i <; i ++) {System.out.println (myObject.getConnection (). HASHCODE ();}}}}}; hasil
1 MyObject Construct dipanggil
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
Di atas merangkum berbagai situasi dan solusi yang dihadapi ketika menggabungkan mode kepentingan tunggal dengan multi-threading, sehingga dapat ditinjau ketika digunakan nanti.