Initialisering-on-demand hållare idiom
Inom mjukvaruteknik är formspråket för initiering -på-begäran ( designmönster ) en lat-laddad singel . I alla versioner av Java möjliggör formspråket en säker, mycket samtidig lat initialisering av statiska fält med bra prestanda.
public class Something { private Something () {} private static class LazyHolder { static final Something INSTANCE = new Something (); } public static Something getInstance () { return LazyHolder . INSTANS ; } }
Implementeringen av formspråket förlitar sig på initieringsfasen av exekvering inom Java Virtual Machine (JVM) som specificeras av Java Language Specification (JLS). När klassen Something
laddas av JVM går klassen igenom initialisering. Eftersom klassen inte har några statiska variabler att initiera, slutförs initieringen trivialt. Den statiska klassdefinitionen LazyHolder
i den initieras inte förrän JVM bestämmer att LazyHolder
måste exekveras. Den statiska klassen LazyHolder
exekveras endast när den statiska metoden getInstance
anropas på klassen Something
, och första gången detta händer kommer JVM att ladda och initiera LazyHolder
-klassen. Initieringen av LazyHolder
resulterar i att den statiska variabeln INSTANCE
initieras genom att exekvera den (privata) konstruktorn för den yttre klassen Something
. Eftersom klassinitieringsfasen garanteras av JLS att vara sekventiell, dvs icke-samtidig, krävs ingen ytterligare synkronisering i den statiska getInstance
-metoden under laddning och initiering. Och eftersom initieringsfasen skriver den statiska variabeln INSTANCE
i en sekventiell operation, kommer alla efterföljande samtidiga anrop av getInstance
att returnera samma korrekt initierade INSTANCE
utan att medföra ytterligare synkroniseringskostnader.
Varningar
Även om implementeringen är en effektiv trådsäker "singleton"-cache utan synkroniseringsoverhead och bättre prestanda än obestridd synkronisering, kan formspråket bara användas när konstruktionen av Something
garanterat inte misslyckas. I de flesta JVM-implementeringar, om konstruktionen av Something
misslyckas, kommer efterföljande försök att initiera det från samma klassladdare att resultera i ett NoClassDefFoundError-
fel.
Se även
externa länkar
- http://www.cs.umd.edu/~pugh/java/memoryModel/
- http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html
- http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html