문제

단일 스레드 응용 프로그램에서 기본 메소드를 제공하는 다른 클래스 (jriengine)를 호출하는 클래스 (rinterfacehl)가 있습니다. 따라서 JVM 당 단일 클래스 (rinterfacehl) 만 갖고 싶습니다.

정적 초기화와 함께 싱글 톤 패턴을 사용하여 rinterfacehl의 단일 인스턴스화 만 보장 할 수 있지만 rinterfacehl은 Jriengine 인스턴스를 구성하고 루프백 매개 변수를 제공해야합니다. 스레드 안전 방식으로 단일 Jriengine의 구성을위한 루프백 매개 변수를 수용하는 Rinterfacehl의 단일 인스턴스를 어떻게 제공 할 수 있습니까? JDK6을 사용하고 있습니다.

NB : 이것 마찬가지로 이름이 지정된 질문은 내 질문에 대답하지 않습니다.

도움이 되었습니까?

해결책

사용하는 싱글 톤 패턴의 수정 Bill Pugh의 초기화에 대한 초기화 보유자 관용구. 이것은 특수 언어 구성 (즉, 휘발성 또는 동기화 된)의 오버 헤드가없는 스레드 안전입니다.

public final class RInterfaceHL {

    /**
     * Private constructor prevents instantiation from other classes.
     */
    private RInterfaceHL() { }

    /**
     * R REPL (read-evaluate-parse loop) handler.
     */
    private static RMainLoopCallbacks rloopHandler = null;

    /**
     * SingletonHolder is loaded, and the static initializer executed, 
     * on the first execution of Singleton.getInstance() or the first 
     * access to SingletonHolder.INSTANCE, not before.
     */
    private static final class SingletonHolder {

        /**
         * Singleton instance, with static initializer.
         */
        private static final RInterfaceHL INSTANCE = initRInterfaceHL();

        /**
         * Initialize RInterfaceHL singleton instance using rLoopHandler from
         * outer class.
         * 
         * @return RInterfaceHL instance
         */
        private static RInterfaceHL initRInterfaceHL() {
            try {
                return new RInterfaceHL(rloopHandler);
            } catch (REngineException e) {
                // a static initializer cannot throw exceptions
                // but it can throw an ExceptionInInitializerError
                throw new ExceptionInInitializerError(e);
            }
        }

        /**
         * Prevent instantiation.
         */
        private SingletonHolder() {
        }

        /**
         * Get singleton RInterfaceHL.
         * 
         * @return RInterfaceHL singleton.
         */
        public static RInterfaceHL getInstance() {
            return SingletonHolder.INSTANCE;
        }

    }

    /**
     * Return the singleton instance of RInterfaceHL. Only the first call to
     * this will establish the rloopHandler.
     * 
     * @param rloopHandler
     *            R REPL handler supplied by client.
     * @return RInterfaceHL singleton instance
     * @throws REngineException
     *             if REngine cannot be created
     */
    public static RInterfaceHL getInstance(RMainLoopCallbacks rloopHandler)
            throws REngineException {
        RInterfaceHL.rloopHandler = rloopHandler;

        RInterfaceHL instance = null;

        try {
            instance = SingletonHolder.getInstance();
        } catch (ExceptionInInitializerError e) {

            // rethrow exception that occurred in the initializer
            // so our caller can deal with it
            Throwable exceptionInInit = e.getCause();
            throw new REngineException(null, exceptionInInit.getMessage());
        }

        return instance;
    }

    /**
     * org.rosuda.REngine.REngine high level R interface.
     */
    private REngine rosudaEngine = null;

    /**
     * Construct new RInterfaceHL. Only ever gets called once by
     * {@link SingletonHolder.initRInterfaceHL}.
     * 
     * @param rloopHandler
     *            R REPL handler supplied by client.
     * @throws REngineException
     *             if R cannot be loaded.
     */
    private RInterfaceHL(RMainLoopCallbacks rloopHandler)
            throws REngineException {

        // tell Rengine code not to die if it can't
        // load the JRI native DLLs. This allows
        // us to catch the UnsatisfiedLinkError
        // ourselves
        System.setProperty("jri.ignore.ule", "yes");

        rosudaEngine = new JRIEngine(new String[] { "--no-save" }, rloopHandler);
    }
}

다른 팁

public class RInterfaceHL {
    private static RInterfaceHL theInstance;

    private final JRIEngine engine;

    private RInterfaceHL(JRIEngine engine) {
        this.engine = engine;
    }

    public static synchronized RInterfaceHL getInstance() {
        if (theInstance == null) {
            throw new IllegalStateException("not initialized");
        }
        return theInstance;
    }
    public static synchronized void initialize(String loopback) {
        if (theInstance != null) {
            throw new IllegalStateException("already initialized");
        }
        theInstance = new RInterfaceHL(new JRIEngine(loopback));
    }

    ...
}

편집 : 서블릿이나 이와 유사한 컨테이너로 실행하기 위해 물건을 만들고 있다면 순수한 싱글 톤 패턴을 사용하는 것은 아마도 나쁜 생각이라고 덧붙여 야합니다. IOC / 의존성 주입 메커니즘 중 하나는 더 나은 아이디어입니다. 예를 들어 또 다른 대답에서 제안 된대로 봄. 이를 통해 "싱글 톤"을 컨테이너로 범위로 범위를 보일 수 있습니다.

작은 응용 프로그램을 수행하는 경우 과잉 일 수 있지만 의존성 주입 프레임 워크 봄 프레임 워크 수동으로 정적 객체를 수동으로 구성하고 초기화 할 필요없이 싱글 톤 동작을 줄 수 있습니다.

의존성 주입 "컨테이너"는 싱글 톤과 그 종속성 클래스를 함께 구성하고 와이어로 만들고 컨테이너 내의 싱글 톤 인스턴스를 만들도록 구성 할 수 있습니다.

전에 봄을 사용하지 않았다면 약간의 학습 곡선이 있지만 정말 인기있는 프레임 워크이며 아마도 당신에게 잘 섬길 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top