Класс Java инициализируется потоком, которые используют его впервые?

Позволяет принимают следующее определение классов:

public class A {
    public final static String SOME_VALUE;

    static {
        SOME_VALUE = "some.value";
    }
}

public class B {
    private final String value = A.SOME_VALUE;
}

Предположение, что класс A еще не был загружен, что действительно происходит, когда объект класса B инстанцирует некоторый поток T? Класс A нужно загрузить и инстанцировать сначала. Но мой вопрос: если это сделано в контексте потока T, или скорее в контексте некоторого другого (специального) потока "classloader"?

5
задан oo_olo_oo 18 March 2010 в 13:04
поделиться

2 ответа

Нет специального потока для загрузки классов. Это будет из потока, который впервые обращается к этому классу. Метод ClassLoader.loadClass синхронизируется, поэтому несколько потоков, пытающихся загрузить один и тот же класс, не мешают.

РЕДАКТИРОВАТЬ Код для перечисления

public class Arbit {
    public static void main(String[] args) throws Exception{
        B b1 = new B("1");
        B b2 = new B("2");
        B b3 = new B("3");
        b1.start();
        b2.start();
        b3.start();
        b1.join();
        b2.join();
        b3.join();
    }
}

class B extends Thread{
    B(String s){
        setName(s);
    }
    @Override
    public void run() {

        try {
            Thread.sleep(new Random().nextInt(100));
        } catch (InterruptedException e) {
        }
        System.out.println(A.s);
    }
}

class A{
    static String s = Thread.currentThread().getName();
}
4
ответ дан 14 December 2019 в 01:05
поделиться

Взгляните на разделы 12.4.1 («Когда происходит инициализация») и 12.4.2 ( «Подробная процедура инициализации») JLS:

Затем процедура инициализации класса или интерфейса выглядит следующим образом:

  1. Синхронизация (§14.19) на объекте Class, который представляет класс или интерфейс, который должен быть инициализирован. Это включает ожидание, пока текущий поток не сможет получить блокировку для этого объекта (§17.1).
  2. Если инициализация класса или интерфейса выполняется каким-либо другим потоком, дождитесь этого объекта класса (который временно снимает блокировку). Когда текущий поток пробуждается от ожидания, повторите этот шаг.
  3. Если инициализация класса или интерфейса выполняется текущим потоком, то это должен быть рекурсивный запрос на инициализацию. Снимите блокировку с объекта Class и завершите работу в обычном режиме.
  4. Если класс или интерфейс уже инициализированы, дальнейшие действия не требуются. Снимите блокировку с объекта Class и завершите работу в обычном режиме.
    ...

В спецификации указано, что инициализация происходит в текущем потоке (что означает, что любой поток достиг состояния, вызывающего необходимость инициализации рассматриваемого класса), но что реализация JVM должна сделать некоторые довольно строгие гарантии синхронизации, чтобы избежать каких-либо проблем.

5
ответ дан 14 December 2019 в 01:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: