2016-01-05 6 views
0

Я работаю над сервлетом, где мне нужно предоставить уникальный запрос каждому запросу и сохранить каждый параметр запроса в таблице аудита. Меня беспокоит работа с грязным чтением в таблицах базы данных, если я пытаюсь увеличить значение, просмотрев таблицу для предыдущего идентификатора. Я хочу знать, если при использовании времени в миллисекундах, когда запрос будет отправлен в сервлет, чтобы решить эту проблему. Я боюсь, если какой-либо другой запрос поступит из другого места географии в тот же самый момент для того же сервлета, чтобы java.lang.System.currentTimeMillis() будет таким же для другого входящего запроса. Причина, по которой я поставил такое сомнение, я считаю, что многопоточность поведения сервлета принимает запрос одновременно, а затем охватывает циклы процессора для каждого запроса на основе некоторого алгоритма.создание уникального идентификатора запроса для каждого запроса с использованием метода timemillis в Servlet

+1

Если у вас есть синхронизированный блок кода, в котором вы получили свой «ключ», вы можете контролировать это. –

+0

Спасибо, что собрали блоки синхронизации, но я беспокоюсь о проблемах с производительностью, поэтому я думал, можно ли использовать время в миллисекундах. Каков ваш комментарий к значению java.lang.System.currentTimeMillis(), чтобы быть уникальным для разных запросов, полученных в одно и то же время для одного и того же сервлета. – user1036204

+1

Время в миллисекундах не гарантирует уникальность. На некоторых ОС он может даже увеличиваться в больших кусках. – Henry

ответ

2

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); 
     } 
    } 
} 
0

Даже синхронизируется неправильно. Вы можете получить одинаковый идентификатор для двух запросов, очень близких по времени. Лучше использовать случайный длинный или последовательный номер.

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 после перезапуска программы.

+0

Интересно, теперь я получил новый способ после прочтения вашего комментария. Если я использую вышеуказанный метод, есть ли шанс, что однажды я получу тот же идентификатор для двух разных запросы на разные даты. В этом случае я могу использовать этот идентификатор и временную метку как unqiue для идентификации уникального запроса. – user1036204

+0

Есть 18 446 744 073 709 551 616 разных длинных значений. Риск столкновения с идентификатором действительно очень низкий. Вам нужно будет обрабатывать миллиарды транзакций каждый день, и шанс все равно будет довольно низким. – aalku

 Смежные вопросы

  • Нет связанных вопросов^_^