цикл java for выполняется слишком быстро, что дает дубликат System.currentTimeMillis () - PullRequest
3 голосов
/ 24 июня 2011

Java: у меня проблема с использованием функции System.currentTimeMillis ()

Я использую System.currentTimeMillis () для генерации уникальных значений в цикле foor. Проблема в том, что цикл выполняется слишком быстро, а System.currentTimeMillis () даетмне повторяющиеся значения.

Как я могу сгенерировать наверняка уникальные значения.

for(int a=0;a<=10;a++){
System.out.println(System.currentTimeMillis())
}

Я также пытался следовать, но это также не является генерацией генерировать уникальное число

System.currentTimeMillis()+Math.random()

Ответы [ 9 ]

6 голосов
/ 24 июня 2011

Почему бы вам не использовать библиотеку UUID для генерации уникальных идентификаторов (уже есть в JDK http://download.oracle.com/javase/6/docs/api/java/util/UUID.html).

Или для более простого подхода: добавить статический счетчик

4 голосов
/ 24 июня 2011

почему бы вам не использовать System.nanoTime() вместо этого?

2 голосов
/ 24 июня 2011

Я думаю, что ваш подход неверен, если это требование.

Теоретически, независимо от того, насколько детализирован ваш таймер, машина может выполнить его за меньшее время, чем таймер.зернистость.Неправильно в техническом смысле полагаться на то, что это правда.

Или смотреть на это иначе - почему вам нужны эти значения, чтобы быть уникальными (для чего вы их используете)?Если вы действительно хотите, чтобы они были мерой времени, когда оно было выполнено, то вы должны быть рады, что две итерации, которые произошли в течение одной миллисекунды, получили одинаковое значение.Счетчик для назначения идентификаторов для каждой итерации, которые являются уникальными в каждом выполнении (AtomicLong отлично подходит для этого)?Что-то вроде следующего очень просто и не имеет проблем с параллелизмом:

public class YourClass {

    private static final AtomicLong COUNTER = new AtomicLong();

    private static nextId() { return COUNTER.getAndIncrement(); }

    // Rest of the class, which calls nextId() when it needs an identifier
}

Если вам нужна информация о синхронизации и уникальность, тогда это два отдельных требования, так почему бы не иметь составной ключсоставленный из времени и произвольный уникальный идентификатор?

2 голосов
/ 24 июня 2011

Ответ очевиден - получи медленный компьютер! Ну, или используйте System.nanoTime, как описано здесь, на SO - System.currentTimeMillis против System.nanoTime . А если серьезно, вы не должны использовать время в качестве генератора уникальных чисел, если вам абсолютно не нужно.

Проблема с использованием системного времени, конечно, заключается в том, что:

  • время, возвращаемое вашей системой звонки округляются в большую сторону степень точности, чем фактическая Время процессора. Если ваше поколение ID код работает быстрее, чем эта степень точность тогда у вас будет столкновение.
  • Если ваш код распространяется и каждый единица работы генерирует идентификаторы тогда вы сталкиваетесь с возможностью идентификации столкновение как отдельный процессор или Ядра процессора выделяют идентификаторы, используя их независимые часы.
  • В таких библиотеках, как Java, которые фактически возвращает системное время на основе настраиваемого пользователем свойства у вас больше шансов столкновение нескольких ID в любое время дата сбрасывается на некоторый период в в прошлом, по любой причине.

Очень хорошая альтернатива генерации уникальных идентификаторов - использовать не столь иронично названный Универсальный уникальный идентификатор . Существует несколько реализаций на разных языках, для Java 5 и выше вы можете использовать класс UUID .

Редактировать : Добавить полезную информацию о UUID.

1 голос
/ 24 июня 2011

Похоже на решение @ Andrej, но сочетает в себе таймер и счетчик, поэтому ваши цифры не должны повторяться, если вы перезапустите приложение.

public enum IdGenerator {
    ;

    private static final AtomicLong COUNTER = new AtomicLong(System.currentTimeMillis()*1000);

    public static long nextId() { return COUNTER.getAndIncrement(); }
}
0 голосов
/ 16 февраля 2018

Мое предложение

    long id = System.currentTimeMillis();
    for (int i = 0; i < 10; i++) {
        //do your work
        id++;
    }
0 голосов
/ 24 июня 2011

Проверьте UUID , а также ...

0 голосов
/ 24 июня 2011

try Math.random () * System.currentTimeMillis ()

вот пример результата

4.1140390961236145E11,
4.405289623285403E11,
6.743938910583776E11,
2.0358542930175632E11,
1.2561886548511025E12,
8.629388909268735E11,
1.158038719369676E12,
2.5899667030405692E11,
7.815373208372445E11,
1.0887553507952611E12,
3.947241572203385E11,
1.6723200316764807E11,
1.3071550541162832E12,
2.079941126415029E11,
1.304485187296599E12,
3.5889095083604164E10,
1.3230275106525027E11,
6.484641777434403E11,
5.109822261418748E11,
1.2291750972884333E12,
8.972865957307518E11,
4.022754883048088E11,
7.997154244301389E11,
1.139245696210086E12,
2.633248409945871E11,
8.699957189419155E11,
9.487098785390422E11,
1.1645067228773708E12,
1.5274939161218903E11,
4.8470112347655725E11,
8.749120668472205E11,
2.435762445513599E11,
5.62884487469596E11,
1.1412787212758718E12,
1.0724213377031631E12,
3.1388106597100226E11,
1.1405727247661633E12,
1.2464739913912961E12,
3.2771161059896655E11,
1.2102869787179648E12,
1.168806596179512E12,
5.871383012375131E11,
1.2765757372075571E12,
5.868323434343102E11,
9.887351363037219E11,
5.392282944314777E11,
1.1926033895638833E12,
6.867917070018711E11,
1.1682059242674294E12,
2.4442056772643954E11,
1.1250254537683052E12,
8.875186600355891E10,
3.46331811747409E11,
1.127077925657995E12,
7.056541627184794E11,
1.308631075052609E12,
7.7875319089675E11,
5.52717019956371E11,
7.727797813063546E11,
6.177219592063667E11,
2.9448141585070874E11,
9.617992263836586E11,
6.762500987418107E11,
1.1954995292124463E12,
1.0741763597148225E12,
1.9915919731861673E11,
9.507720563185525E11,
1.1009594810160002E12,
4.1381256571745465E11,
2.2526550777831213E11,
2.5919816802026202E11,
3.8453225321522577E11,
3.796715779825083E11,
6.512277843921505E10,
1.0483456960599313E12,
1.0725956186588704E11,
5.701504883615902E11,
9.085583903150035E11,
1.2764816439306753E12,
1.033783414053437E12,
1.188379914238302E12,
6.42733442524156E11,
3.911345432964901E11,
7.936334657654698E11,
1.4473479058272617E11,
1.2030471387183499E12,
5.900668555531211E11,
8.078992189613184E11,
1.2004364275316113E12,
1.250275098717202E12,
2.856556784847933E11,
1.9118298791320355E11,
5.4291847597892596E11,
3.9527733898520874E11,
6.384539941791654E11,
1.2812873515441786E11,
6.325269269733575E9,
5.403119000792323E11,
8.023708335126083E11,
3.761680594623883E10,
1.2641772837928888E11,
0 голосов
/ 24 июня 2011

Если вы все еще хотите использовать свой метод, вы можете сделать:

for(int a=0;a<=10;a++){
    Thread.sleep(1);
    System.out.println(System.currentTimeMillis())
}

Явно замедляет ваш процессор.

...