Pola singleton adalah yang termudah untuk dipahami dan cara termudah untuk menulis kode dalam pola desain, tetapi tidak ada banyak poin pengetahuan yang terlibat, sehingga sering digunakan sebagai pertanyaan wawancara. Secara umum, singleton ditulis dalam lima cara: malas, lapar, kunci cek ganda, kelas internal statis dan enumerasi. Untuk merekam proses pembelajaran, beberapa metode penulisan singleton umum telah dikompilasi di sini.
Bronze 5: (malas malas, tetapi utas tidak aman)
Ketika ditanya tentang menerapkan pola singleton, reaksi pertama banyak orang adalah menulis kode berikut, termasuk ajaran yang sama di buku teks.
Singleton kelas publik {instance singleton statis privat; private singleton () {} public static singleton getInstance () {if (instance == null) {instance = new singleton (); } return instance; }}Kode ini sederhana dan mudah, dan menggunakan mode pemuatan yang tertunda, tetapi utas tidak aman. Memanggil metode getInstance () dalam lingkungan multi-threaded dapat menyebabkan banyak utas untuk memasukkan blok kode program dari pernyataan IF.
Gaya Lazy: Sinkronisasi (malas yang dimuat, aman-aman, tetapi tidak efisien)
Untuk menyelesaikan masalah di atas, cara termudah adalah dengan mengatur seluruh metode getInstance () untuk disinkronkan.
Singleton kelas publik {instance singleton statis privat; private singleton () {} public static Synchronized singleton getInstance () {if (instance == null) {instance = new singleton (); } return instance; }}Meskipun aman dan tertunda pemuatan, itu tidak efisien. Karena kapan saja hanya ada satu utas yang memanggil metode getInstance (). Namun, operasi yang disinkronkan hanya perlu dibutuhkan pada panggilan pertama, yaitu, ketika objek instance singleton dibuat untuk pertama kalinya. Pola ini hanya menyebabkan satu utas mengakses metode getInstance () pada satu waktu bahkan setelah singleton dibuat, yang dapat menyebabkan masalah kinerja potensial. Ini mengarah ke kunci cek ganda.
Gaya Lapar: Bidang Akhir Statis (Non-Lazy-Ly)
Metode ini sangat sederhana, karena contoh singleton dinyatakan sebagai final statis dan diinisialisasi ketika kelas dimuat ke dalam memori untuk pertama kalinya, sehingga membuat objek instance-aman (dijamin oleh implementasi JVM).
Singleton kelas publik {// menginisialisasi private static final singleton instance = new singleton (); private singleton () {} public static singleton getInstance () {// singleton dengan instance pengembalian pabrik statis; }}Ini bukan mode pemuatan malas, instance akan diinisialisasi dari awal setelah kelas dimuat, bahkan jika klien tidak memanggil metode getInstance (). Ini akan mengarah pada beberapa pembatasan penggunaan: misalnya, pembuatan instance singleton tergantung pada parameter atau file konfigurasi. Sebelum getInstance (), metode tertentu harus dipanggil untuk mengatur parameter untuk itu, sehingga metode penulisan singleton ini tidak akan digunakan. Metode serupa termasuk:
Public Class Singleton {public static final singleton instance = new singleton (); // singleton dengan bidang akhir publik singleton pribadi () {}} // <Efektif java> halaman 14 memberi tahu perbedaan antara keduanyaKunci Periksa Ganda + Volatile (Lazyload, Thread-Safe, tapi tidak jelas)
Pola penguncian yang diperiksa ganda adalah metode penguncian menggunakan blok sinkron. Programmer menyebutnya kunci cek ganda karena akan ada dua contoh cek == null, sekali di luar blok sinkronisasi dan sekali di dalam blok sinkronisasi. Mengapa kita perlu memeriksa lagi di blok sinkronisasi? Karena beberapa utas dapat masuk jika di luar blok sinkronisasi bersama -sama, jika tidak ada verifikasi sekunder yang dilakukan di blok sinkronisasi, beberapa objek instance akan dihasilkan.
public static singleton getseLleton () {if (instance == null) {// single scenned disinkronkan (singleton.class) {if (instance == null) {// double checked instance = singleton baru (); }}} return instance;}Kode ini terlihat sempurna, tapi sayangnya itu bermasalah. Hal utama adalah contoh kalimat = singleton baru (). Ini bukan operasi atom. Bahkan, kalimat ini dalam JVM melakukan kira -kira 3 hal berikut.
Namun, ada optimalisasi instruksi ulang instruksi di JVM's JIT Compiler. Dengan kata lain, urutan langkah kedua dan ketiga di atas tidak dapat dijamin, dan perintah eksekusi akhir mungkin 1-2-3 atau 1-3-2. Jika yang terakhir, itu akan didahului oleh Thread 2 sebelum eksekusi 3 dan 2 tidak dieksekusi. Pada saat ini, instance sudah non-null (tetapi tidak diinisialisasi), jadi Thread 2 akan secara langsung mengembalikan instance, kemudian menggunakannya, dan kemudian secara alami melaporkan kesalahan. Untuk melakukan ini, kita perlu mendeklarasikan variabel instance sebagai volatile.
Singleton kelas publik {instance singleton statis volatile privat; // Deklarasikan sebagai singleton privat yang mudah menguap () {} public static singleton getseLleton () {if (instance == null) {disinkronkan (singleton.class) {if (instance == null) {instance = new singleton (); }} return instance; }}Namun, penting untuk dicatat bahwa masih ada masalah dengan kunci ganda-cek yang mudah menguap dalam versi sebelum Java 1.5. Masalah ini hanya diperbaiki di Java 1.5, sehingga Anda dapat menggunakan volatile setelah itu.
Kelas Dalam Statis: IODH, pemegang inisialisasi-atas-permintaan
Pola ini menggabungkan kelas internal statis Java dan pengetahuan kunci sinkronisasi default multi-threaded, dan dengan cerdik mengimplementasikan pemuatan latensi dan keselamatan benang.
kelas publik singleton {private singleton () {} private static class lazyHolder {private static final singleton instance = new singleton (); } public static singleton getInstance () {// dari wikipedia return lazyholder.instance; }}Kelas dalam statis setara dengan bagian statis dari kelas luarnya. Objeknya tidak bergantung pada objek kelas eksternal, sehingga dapat dibuat secara langsung. Kelas internal statis hanya akan direproduksi ketika digunakan untuk pertama kalinya.
Kunci sinkronisasi default multithreaded
Seperti yang kita semua ketahui, dalam pengembangan multi-threaded, untuk menyelesaikan masalah konkurensi, terutama untuk menggunakan disinkronkan untuk menambahkan mutex untuk kontrol sinkronisasi. Tetapi dalam beberapa kasus, JVM sudah secara implisit melakukan sinkronisasi untuk Anda, dan dalam kasus ini tidak perlu melakukan kontrol sinkronisasi secara manual. Situasi ini meliputi :
1. Saat menginisialisasi data dengan inisialisasi statis (inisialisasi pada bidang statis atau di blok {} statis)
2. Saat mengakses bidang terakhir
3. Saat membuat objek sebelum membuat utas
4. Saat utas dapat melihat objek yang akan diprosesnya
Enum
Mulai dari Java 1.5, cukup tulis tipe enum yang berisi satu elemen:
publik enum singleton {instance;}Metode ini secara fungsional mirip dengan metode domain publik, tetapi lebih ringkas dan memberikan mekanisme serialisasi secara gratis, benar -benar mencegah beberapa instantiasi, bahkan ketika menghadapi serialisasi yang kompleks atau serangan refleksi. Meskipun pendekatan ini belum diadopsi secara luas, jenis -jenis elemen tunggal telah menjadi cara terbaik untuk mengimplementasikan Singleton.
-----------------------------------------------------------------------------------------------------------------------------
1. Apa rincian final statis
2. Apakah inisialisasi penugasan di bidang statis secara berurutan dan blok kode statis?
3. Cara Menulis Pola Singleton Untuk Kelas Internal Statis
4. Apakah contoh -contoh dalam analisis dan aplikasi pola desain Java EE benar -benar memiliki efek malas?
Di atas adalah semua konten artikel ini. Saya berharap konten artikel ini akan membantu untuk belajar atau bekerja semua orang. Saya juga berharap untuk mendukung wulin.com lebih lanjut!