Кіріспе
Бағдарламалық жасақтауда талап бойынша инициализациялау (конструкторлық үлгі) идиомасы - жалқау жүктелген синглтон. Java-ның барлық нұсқаларында идиома жақсы өнімділікпен статикалық өрістерді қауіпсіз, өте бір мезгілде жалкоо бастауды қамтамасыз етеді. public class Something { private Something {} private static class LazyHolder { static final Something INSTANCE = new Something ; } public static Something getInstance { return LazyHolder. INSTANCE; } } Идиоманың іске асырылуы Java Language Specification (JLS) -де көрсетілгендей Java Virtual Machine (JVM) -де орындалудың инициализациялық фазасына байланысты . Something класы JVM жүктегенде, класс инициализациялаудан өтеді. Сабақтың бастауыштайтын статикалық айнымалылары болмағандықтан, бастауыштайту тривиальді түрде аяқталады. Оның ішіндегі LazyHolder статикалық сынып анықтамасы JVM LazyHolder орындалуы керек деп анықтағанша инициализацияланбайды. LazyHolder статикалық класы тек getInstance статикалық әдісі Something класына шақырылған кезде орындалады, ал бұл бірінші рет JVM жүктеледі және LazyHolder класын бастамалайды. LazyHolder класының инициализациясы сыртқы Something класының (жеке) конструкторын орындау арқылы INSTANCE статикалық айнымалының инициализациялануына әкеледі. Сабақтарды инициализациялау кезеңі JLS-пен бірізді, яғни бір мезгілде емес болуына кепілдік берілгендіктен, жүктеу мен инициализациялау кезінде статикалық getInstance әдісінде қосымша синхрондау талап етілмейді. Бастапқылау кезеңі статикалық айнымалы INSTANCE-ді ретті операцияда жазатындықтан, getInstance-тің барлық келесі бір мезгілде шақырылуы қосымша синхрондау шығынысыз дәл дұрыс басталған INSTANCE-ті қайтарады.
private Something {}
private static class LazyHolder {
static final Something INSTANCE = new Something ;
}
public static Something getInstance {
return LazyHolder. INSTANCE;
}
}
The implementation of the idiom relies on the initialization phase of execution within the Java Virtual Machine (JVM) as specified by the Java Language Specification (JLS). When the class Something is loaded by the JVM, the class goes through initialization. Since the class does not have any static variables to initialize, the initialization completes trivially. The static class definition LazyHolder within it is not initialized until the JVM determines that LazyHolder must be executed. The static class LazyHolder is only executed when the static method getInstance is invoked on the class Something, and the first time this happens the JVM will load and initialize the LazyHolder class. The initialization of the LazyHolder class results in static variable INSTANCE being initialized by executing the (private) constructor for the outer class Something. Since the class initialization phase is guaranteed by the JLS to be sequential, i. e., non concurrent, no further synchronization is required in the static getInstance method during loading and initialization. And since the initialization phase writes the static variable INSTANCE in a sequential operation, all subsequent concurrent invocations of the getInstance will return the same correctly initialized INSTANCE without incurring any additional synchronization overhead.
Қақпақтар
Реализация тиімді, синхрондауды үстіртпей, тиімді және ұдайы синхрондауға қарағанда жақсы жұмыс істейтін, бірақ бұл идиомды тек бір нәрсенің құрылымы сәтсіздікке ұшырамайтынына кепілдік берілген кезде ғана қолдануға болады. JVM-нің көпшілігінде, егер Something құрылымы сәтсіз болса, оны сол сынып жүктеушіден бастауды жалғастыруға тырысу NoClassDefFoundError қатесіне әкеледі.