Как сделать статический поток календаря безопасным
Я хотел бы использовать календарь для некоторых статических методов и использовать статическое поле:
private static Calendar calendar = Calendar.getInstance();
Теперь я читаю java.util.Calendar не является потокобезопасным. Как я могу сделать этот поток безопасным (он должен быть статическим)?
Ответы
Ответ 1
Вы не можете сделать что-то потокобезопасным, если это не так. В случае Calendar
даже чтение данных из него не является потокобезопасным, так как оно может обновлять внутренние структуры данных.
Если это вообще возможно, я бы предложил вместо Joda Time:
- Большинство типов являются неизменяемыми.
- Неизменяемые типы являются потокобезопасными
- В общем, это намного лучший API
Если вам абсолютно необходимо использовать Calendar
, вы можете создать объект блокировки и поместить весь доступ через блокировку. Например:
private static final Calendar calendar = Calendar.getInstance();
private static final Object calendarLock = new Object();
public static int getYear()
{
synchronized(calendarLock)
{
return calendar.get(Calendar.YEAR);
}
}
// Ditto for other methods
Это довольно неприятно. У вас может быть только один синхронизированный метод, который создавал клон исходного календаря каждый раз, когда это было необходимо, конечно... возможно, что, вызывая computeFields
или computeTime
, вы можете сделать последующие операции чтения с потоком Конечно, но лично я был бы не против, чтобы попробовать.
Ответ 2
Календарь является потокобезопасным, если вы его не изменяете. Использование в вашем примере прекрасно.
Стоит отметить, что Календарь не является эффективным классом, и вы должны использовать его только для сложных операций (например, поиск следующего месяца/года). IMHO: Если вы используете его для сложных операций, используйте только локальные переменные.
Если вы хотите, чтобы это был моментальный снимок времени, более быстрый способ - использовать currentTimeMillis, который даже создает объект. Вы можете сделать поле volatile, если вы хотите сделать его потокобезопасным.
private static long now = System.currentTimeMillis();
Использование немного подозрительно. Зачем вам получать текущее время и хранить его в глобальном масштабе. Это напоминает мне старую шутку.
- У вас есть время?
- Да, я его где-то записал.
Ответ 3
Вы не можете. Да, вы можете синхронизировать его, но у него все еще есть изменяемые поля состояния. Вам нужно будет создать свой собственный объект Calendar.
Если возможно, используйте что-то легкое, как длинное измерение времени в миллисекундах, и только конвертируйте в Календарь, когда вам НУЖНО.
Ответ 4
Создайте Calendar
как локальную переменную в методе. Если вам нужен один и тот же календарь в разных методах, вы можете использовать статику, где более подходящим является объект (singleton или quasi-singleton).