Я работаю над сервлетом, где мне нужно предоставить уникальный запрос каждому запросу и сохранить каждый параметр запроса в таблице аудита. Меня беспокоит работа с грязным чтением в таблицах базы данных, если я пытаюсь увеличить значение, просмотрев таблицу для предыдущего идентификатора. Я хочу знать, если при использовании времени в миллисекундах, когда запрос будет отправлен в сервлет, чтобы решить эту проблему. Я боюсь, если какой-либо другой запрос поступит из другого места географии в тот же самый момент для того же сервлета, чтобы java.lang.System.currentTimeMillis() будет таким же для другого входящего запроса. Причина, по которой я поставил такое сомнение, я считаю, что многопоточность поведения сервлета принимает запрос одновременно, а затем охватывает циклы процессора для каждого запроса на основе некоторого алгоритма.создание уникального идентификатора запроса для каждого запроса с использованием метода timemillis в Servlet
ответ
System.currentTimeMillis()
не гарантирует уникальность при вызове нескольких потоков. Столкнувшись с такой ситуацией в прошлом я использовал AtomicLong для создания уникальных идентификаторов - это класс getAndIncremenet
должен быть безблокировочным (и, следовательно, достаточно эффективно) на большинстве виртуальных машин
public class IdUtil {
private static final AtomicLong counter = new AtomicLong(System.currentTimeMillis());
// return a single id
public static long getId() {
return counter.getAndIncrement();
}
// return a block of ids
public static Queue<Long> getIds(long span) {
long max = counter.addAndGet(span);
Queue<Long> queue = new ArrayDeque<>(span);
for(int i = max - span; i < max; i++) {
queue.add(i);
}
}
}
Даже синхронизируется неправильно. Вы можете получить одинаковый идентификатор для двух запросов, очень близких по времени. Лучше использовать случайный длинный или последовательный номер.
private static final Random r = new Random(); // <- shared resource
// ...
long id = r.nextLong();
или
private static final AtomicLong counter = new AtomicLong(System.currentTimeMillis()); // <- shared resource
// ...
long id = counter.getAndIncrement();
counter
инициализируется миллисекунд, так что не обеспечивает ту же последовательность ID после перезапуска программы.
Интересно, теперь я получил новый способ после прочтения вашего комментария. Если я использую вышеуказанный метод, есть ли шанс, что однажды я получу тот же идентификатор для двух разных запросы на разные даты. В этом случае я могу использовать этот идентификатор и временную метку как unqiue для идентификации уникального запроса. – user1036204
Есть 18 446 744 073 709 551 616 разных длинных значений. Риск столкновения с идентификатором действительно очень низкий. Вам нужно будет обрабатывать миллиарды транзакций каждый день, и шанс все равно будет довольно низким. – aalku
Если у вас есть синхронизированный блок кода, в котором вы получили свой «ключ», вы можете контролировать это. –
Спасибо, что собрали блоки синхронизации, но я беспокоюсь о проблемах с производительностью, поэтому я думал, можно ли использовать время в миллисекундах. Каков ваш комментарий к значению java.lang.System.currentTimeMillis(), чтобы быть уникальным для разных запросов, полученных в одно и то же время для одного и того же сервлета. – user1036204
Время в миллисекундах не гарантирует уникальность. На некоторых ОС он может даже увеличиваться в больших кусках. – Henry