Кто-то где-то сказал мне, что конструкторы Java синхронизированы, так что к ним нельзя одновременно обращаться во время построения, и мне было интересно: если у меня есть конструктор, который хранит объект на карте, а другой поток извлекает его с этой карты до того, как его конструкция будет завершена, будет ли этот поток блокироваться до завершения конструктора?
Позвольте мне продемонстрировать код:
public class Test {
private static final Map<Integer, Test> testsById =
Collections.synchronizedMap(new HashMap<>());
private static final AtomicInteger atomicIdGenerator = new AtomicInteger();
private final int id;
public Test() {
this.id = atomicIdGenerator.getAndIncrement();
testsById.put(this.id, this);
// Some lengthy operation to fully initialize this object
}
public static Test getTestById(int id) {
return testsById.get(id);
}
}
Предположим, что put/get являются единственными операциями на карте, поэтому я не получу CME через что-то вроде итерации и стараюсь игнорировать другие очевидные недостатки.
Что я хочу знать, если другой поток (который не тот, который строит объект, очевидно) пытается получить доступ к объекту с помощью getTestById
и вызывать что-то на нем, будет ли он блокироваться? Другими словами:
Test test = getTestById(someId);
test.doSomething(); // Does this line block until the constructor is done?
Я просто пытаюсь выяснить, насколько далеко идет синхронизация конструктора в Java, и если такой код будет проблематичным. Я недавно видел такой код, который сделал это вместо использования статического метода factory, и мне было интересно, насколько опасно (или безопасно) это в многопоточной системе.