Как синхронизировать статический метод в Java
Я придумал этот вопрос при реализации одноэлементного шаблона в Java. Хотя приведенный ниже пример не является моим реальным кодом, но очень похож на исходный.
public class ConnectionFactory{
private static ConnectionFactory instance;
public static synchronized ConnectionFactory getInstance(){
if( instance == null ){
instance = new ConnectionFactory();
}
return instance;
}
private ConnectionFactory(){
// private constructor implementation
}
}
поскольку я не совсем уверен в поведении статического синхронизированного метода, я получаю некоторые предложения от google-не имеют (или как можно меньше) несколько статических синхронизированных методов в одном классе. Я предполагаю, что при реализации статического синхронизированного метода блокировка принадлежит классу объект используется для того, чтобы несколько статических синхронизированных методов могли снизить производительность системы.
Я прав? или JVM использует другой механизм для реализации статического синхронизированного метода? Какова наилучшая практика, если мне нужно реализовать несколько статических синхронизированных методов в классе?
спасибо всем!
С уважением!
5 ответов
лучший подход (который делает как можно меньше изменений в вашем коде) заключается в следующем:
public class ConnectionFactory{
private static ConnectionFactory instance = new ConnectionFactory();
public static ConnectionFactory getInstance(){
return instance;
}
private ConnectionFactory(){
}
}
как вы можете видеть, нет никакой реальной необходимости в getInstance
способ сейчас, так что вы можете упростить код:
public class ConnectionFactory{
public static final ConnectionFactory INSTANCE = new ConnectionFactory();
private ConnectionFactory(){
}
}
UPD о синхронизации: лучший способ-синхронизация на блокировке, которая не видна внешним классам, т. е.:
public class ConnectionFactory{
private static final Object lock = new Object();
public static void doSmth() {
synchronized (lock) {
...
}
}
public static void doSmthElse() {
synchronized (lock) {
...
}
}
}
есть много дискуссий о " почему синхронизация на this
- это плохая идея" (например,этот один), Я думаю, что то же самое актуально для синхронизации на классе.
существует несколько способов создания синглтона.
один из рекомендуемых способов - использовать перечисление (гарантируется создание только одного экземпляра):
public enum ConnectionFactory {
INSTANCE;
}
или вы можете создать его статически, когда класс нагрузки:
public class ConnectionFactory {
private static ConnectionFactory INSTANCE = new ConnectionFactory();
private ConnectionFactory() {}
public static ConnectionFactory getInstance() {
return INSTANCE;
}
}
Если вам нужно, чтобы лениво загрузить его вы можете использовать эту идиому (а не двойная проверка блокировки анти-шаблон )
public class ConnectionFactory {
private static class ConnectionFactoryHolder {
private static ConnectionFactory INSTANCE = new ConnectionFactory();
}
public static ConnectionFactory getInstance() {
return ConnectionFactoryHolder.INSTANCE;
}
}
да, статические методы синхронизируются на их объекте класса. Я бы не беспокоился о производительности здесь, так как, вероятно, это не будет вашей горячей точкой. Сделайте это просто, оптимизируйте, когда и где вам нужно.
статические синхронизированные методы используют блокировку класса. В случае вашего примера это будет доступ к блокировке объекта класса ConnectionFactory. Лучшая практика - не держать замки дольше, чем вам нужно. Наличие нескольких синхронизированных методов само по себе не является проблемой.
Эффективная Java рекомендует использовать перечисления для создания синглтона. Тогда ваш код будет выглядеть примерно так:
public enum ConnectionFactory{
INSTANCE;
// Other factory methods go here.
}
}