정적 코드 블록을 사용하여 레지스트리의 일부 컨트롤러를 초기화하고 있습니다. 내 질문은 따라서이 정적 코드 블록이 클래스가 처음로드 될 때 절대적으로 한 번만 호출된다는 것을 보장 할 수 있습니까? 이 코드 블록이 언제 호출되는지 보장 할 수 없다는 것을 이해합니다. 클래스 로더가 처음로드 할 때 추측합니다. 정적 코드 블록의 클래스에서 동기화 할 수 있다는 것을 알고 있지만 실제로는 이것이 실제로 어떻게됩니까?
간단한 코드 예제는 다음과 같습니다.
class FooRegistry {
static {
//this code must only ever be called once
addController(new FooControllerImpl());
}
private static void addController(IFooController controller) {
// ...
}
}
아니면 내가해야합니까;
class FooRegistry {
static {
synchronized(FooRegistry.class) {
addController(new FooControllerImpl());
}
}
private static void addController(IFooController controller) {
// ...
}
}
답변
예, Java 정적 초기화 프로그램은 스레드로부터 안전합니다 (첫 번째 옵션 사용).
그러나 코드가 정확히 한 번만 실행되도록하려면 단일 클래스 로더 만 클래스를로드해야합니다. 정적 초기화는 클래스 로더 당 한 번 수행됩니다.
답변
게으른 초기화에 사용할 수있는 트릭입니다
enum Singleton {
INSTANCE;
}
또는 Java 5.0 이전
class Singleton {
static class SingletonHolder {
static final Singleton INSTANCE = new Singleton();
}
public static Singleton instance() {
return SingletonHolder.INSTANCE;
}
}
SingletonHolder의 정적 블록은 스레드 안전 방식으로 한 번 실행되므로 다른 잠금이 필요하지 않습니다. singletonHolder 클래스는 instance ()를 호출 할 때만로드됩니다.
답변
일반적인 상황에서는 정적 이니셜 라이저의 모든 것이 해당 클래스를 사용하는 모든 것보다 먼저 발생하므로 일반적으로 동기화가 필요하지 않습니다. 그러나 클래스는 정적 intiailiser가 호출하는 모든 항목에 액세스 할 수 있습니다 (다른 정적 초기자를 호출하는 것을 포함하여).
클래스는로드 된 클래스에 의해로드 될 수 있지만 반드시 즉시 초기화 될 필요는 없습니다. 물론 클래스는 클래스 로더의 여러 인스턴스에 의해로드 될 수 있으며 같은 이름을 가진 여러 클래스가 될 수 있습니다.
답변
예, 일종의
static
초기화는 그래서 정의 그것의 스레드 안전에 의해 한 번 호출됩니다 – 당신은 두 개 이상의 호출이 필요할 것 static
조차 얻을 스레드 경합 이니셜 라이저.
즉, static
이니셜 라이저는 다른 많은 방법으로 혼란스러워합니다. 그들이 부르는 순서는 실제로 없습니다. static
이니셜 라이저가 서로 의존하는 두 개의 클래스가 있으면 혼란 스럽습니다 . 클래스를 사용하지만 static
초기화 프로그램이 설정 한 것을 사용하지 않으면 클래스 로더가 정적 초기화 프로그램을 호출한다고 보장 할 수 없습니다.
마지막으로 동기화하려는 객체를 명심하십시오. 나는 이것이 실제로 당신이 요구하는 것이 아니라는 것을 알고 있지만, addController()
스레드 안전 을 만들어야하는지 질문하지 않아야 합니다.
답변
예, 정적 이니셜 라이저는 한 번만 실행됩니다. 자세한 내용은 이것을 읽으십시오 .
답변
따라서 기본적으로 싱글 톤 인스턴스를 원하기 때문에 어느 정도 구식 방식으로 싱글 톤 객체를 한 번만 초기화해야합니다.