Saya menggunakan blok kode statis untuk menginisialisasi beberapa pengontrol di registri yang saya miliki. Oleh karena itu, pertanyaan saya adalah, dapatkah saya menjamin bahwa blok kode statis ini hanya akan benar-benar dipanggil sekali ketika kelas pertama kali dimuat? Saya mengerti bahwa saya tidak dapat menjamin kapan blok kode ini akan dipanggil, saya menduga ketika Classloader memuatnya pertama kali. Saya menyadari bahwa saya dapat melakukan sinkronisasi di kelas dalam blok kode statis, tetapi tebakan saya apakah ini sebenarnya yang terjadi?
Contoh kode sederhana adalah;
class FooRegistry {
static {
//this code must only ever be called once
addController(new FooControllerImpl());
}
private static void addController(IFooController controller) {
// ...
}
}
atau haruskah saya melakukan ini;
class FooRegistry {
static {
synchronized(FooRegistry.class) {
addController(new FooControllerImpl());
}
}
private static void addController(IFooController controller) {
// ...
}
}
Jawaban:
Ya, penginisialisasi statis Java adalah thread safe (gunakan opsi pertama Anda).
Namun, jika Anda ingin memastikan bahwa kode dijalankan tepat setelah Anda perlu memastikan bahwa kelas tersebut hanya dimuat oleh satu class-loader. Inisialisasi statis dilakukan sekali per pemuat kelas.
sumber
Ini adalah trik yang dapat Anda gunakan untuk inisialisasi lambat
enum Singleton { INSTANCE; }
atau untuk pra Java 5.0
class Singleton { static class SingletonHolder { static final Singleton INSTANCE = new Singleton(); } public static Singleton instance() { return SingletonHolder.INSTANCE; } }
Karena blok statis di SingletonHolder akan berjalan satu kali dengan cara yang aman, Anda tidak memerlukan penguncian lainnya. Kelas SingletonHolder hanya akan dimuat ketika Anda memanggil instance ()
sumber
INSTANCE
bidang telah dideklarasikan secara langsungSingleton
(seperti kasusenum
varian).Dalam keadaan biasa, semua yang ada di penginisialisasi statis terjadi sebelum semua yang menggunakan kelas itu, jadi sinkronisasi biasanya tidak diperlukan. Namun, kelas dapat diakses oleh semua yang dipanggil oleh intiailiser statis (termasuk menyebabkan inisialisasi statis lainnya dipanggil).
Kelas dapat dimuat oleh kelas yang dimuat tetapi tidak harus langsung dijalankan. Tentu saja, kelas dapat dimuat oleh beberapa contoh pemuat kelas dan dengan demikian menjadi beberapa kelas dengan nama yang sama.
sumber
Ya, semacam itu
Sebuah
static
initializer hanya dipanggil sekali, sehingga dengan itu definisi itu thread aman - Anda akan perlu dua atau lebih doa daristatic
initializer bahkan mendapatkan benang pertengkaran.Yang mengatakan,
static
penginisialisasi membingungkan dalam banyak hal lain. Sebenarnya tidak ada urutan tertentu untuk memanggilnya. Ini menjadi sangat membingungkan jika Anda memiliki dua kelas yangstatic
penginisialisasinya bergantung satu sama lain. Dan jika Anda menggunakan kelas tetapi tidak menggunakan apa yangstatic
akan disiapkan penginisialisasi, Anda tidak dijamin pemuat kelas akan memanggil penginisialisasi statis.Terakhir, ingatlah objek yang Anda sinkronkan. Saya menyadari ini bukan yang Anda tanyakan, tetapi pastikan pertanyaan Anda tidak benar-benar menanyakan apakah Anda perlu membuat
addController()
thread-safe.sumber
Ya, penginisialisasi statis dijalankan hanya sekali. Baca ini untuk informasi lebih lanjut .
sumber
Jadi pada dasarnya, karena Anda menginginkan instance tunggal, Anda harus melakukannya kurang lebih dengan cara lama dan memastikan objek tunggal Anda diinisialisasi sekali dan hanya sekali.
sumber