A lusta tartó a számítógép-programozásban egy lusta betöltésű egyke programtervezési minta. A Java minden verziója szálbiztosan valósítja meg a lusta inicializációt. Ennek az a feltétele, hogy a példányt ne lehessen elérni a csomagon kívül. A duplán ellenőrzött zárolást a Java 1.5 előtti verziók nem biztosították.INSTANCE should be package private

public class Something { private Something() {}

private static class LazyHolder { static final Something INSTANCE = new Something();

public static Something getInstance() { return LazyHolder.INSTANCE;

A megvalósítás az inicializáció szakaszára hagyatkozik, amit a Java specifikációja (JLS) is előír. Ha a virtuális gép betölti a Something osztályt, akkor inicializálnia kell. Mivel nincsenek osztályváltozók, az inicializáció triviális. A LazyHolder osztály szintű osztálydefiníció mindaddig nem inicializálódik, amíg nem kell végrehajtani. Ehhez meg kell hívni a Something osztály getInstance metódusát. A LazyHolder inicializációjának eredménye az INSTANCE osztályváltozó, amit a külső osztály privát konstruktora inicializál. Mivel az osztály inicializációja a Java specifikációja szerint szekvenciális, nincs szükség további szinkronizációra. És mivel az inicializációs szakasz szekvenciális műveletben írja az INSTANCE változót, a getInstance minden konkurens hívása ugyanazt a korrektül inicializált INSTANCE példányt adja vissza minden szinkronizációs adminisztráció nélkül.

A minta előnye, hogy hatékony és szálbiztos egykét nyújt szinkronizáció nélkül, és hatékonyabb, mint a megvárakoztató szinkronizáció. Nem alkalmas arra, hogy olyan osztályt inicializáljon, amiből több példányra lenne szükség.

Alkalmazásakor biztosítani kell, hogy a Something konstrukciója garantáltan sikeres legyen. Ugyanis ha a JVM nem tudja inicializálni az osztályt, akkor a betöltő NoClassDefFoundError hibával leáll.

Példa:

public class PughFail { public static class Something { private Something() { super(); System.out.println(this.getClass().getName() + " called"); if (System.currentTimeMillis() > 0) { System.out.println("EMULATING INIT FAILURE"); throw new RuntimeException("EMULATING INIT FAILURE");

private static class LazyHolder { private static final Something INSTANCE = new Something();

public static Something getInstance() { return LazyHolder.INSTANCE;

public static void main(String[] args) { System.out.println("First try"); try { Something.getInstance(); } catch (Throwable t) { System.out.println(t);

System.out.println("Second try"); try { Something.getInstance(); } catch (Throwable t) { System.out.println(t);

Eredmény: First try PughFail$Something called EMULATING INIT FAILURE java.lang.ExceptionInInitializerError Second try java.lang.NoClassDefFoundError: Could not initialize class PughFail$Something$LazyHolder

Források 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 Jegyzetek

Fordítás

Kategória:Programtervezési minták Kategória:Java-kódpéldák