5

Java: I have a problem using System.currentTimeMillis() function

i am using System.currentTimeMillis() to generate unique values in foor loop problem is loop executes too fast and System.currentTimeMillis() gives me duplicate values.

How can i generate for sure unique values.

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

I also tried following but it is also not generaet to generate unique number

System.currentTimeMillis()+Math.random()
d-man
  • 57,473
  • 85
  • 212
  • 296

9 Answers9

6

why don't you use System.nanoTime() instead?

Liv
  • 6,006
  • 1
  • 22
  • 29
  • 1
    If i execute more at more fast machine are there any chances to make it duplicate value? – d-man Jun 24 '11 at 15:54
  • 3
    From the JavaDoc: "No guarantees are made about how frequently values change." You could **easily** run into an implementation that doesn't change any more frequently than `currentTimeMillis()`. – Joachim Sauer Jun 24 '11 at 15:55
  • I agree with @Perception that you shouldn't use system timer for unique number generation : even if your system is slow enough not to generate the same ID per each iteration, what happens if you have this running on multi-processor architectures, where 2 threads could concurrently run at the same time and end up with the same id's. How about using something like this instead: http://www.javapractices.com/topic/TopicAction.do?Id=56 – Liv Jun 24 '11 at 15:57
  • 1
    @ Faisal I get duplicate values – sealz Jun 24 '11 at 15:57
  • I agree if specially comparing in a loop we should not i like the idea have random UUID – d-man Jun 24 '11 at 16:00
  • I am going to use UUID as random image name will it ever UUID chars exceed file name chars ? – d-man Jun 24 '11 at 16:02
  • Timestamps and random numbers cannot be used if you require uniqueness. It's mathematically incorrect. You have to use UUID, a static counter, or a cluster-singleton counter of some sort. – Joshua Davis Jun 25 '11 at 05:01
6

Why don't you use a UUID library to generate unique identifiers (already there in the JDK http://download.oracle.com/javase/6/docs/api/java/util/UUID.html).

Or for a more simple approach: append a static counter

leifg
  • 8,668
  • 13
  • 53
  • 79
2

The answer is obvious - get a slower computer! Well, that or use System.nanoTime as described right here on SO - System.currentTimeMillis vs System.nanoTime. But seriously, you shouldn't be using time as unique number generator unless you absolutely have to.

The problem with using the system time of course being that:

  • The time returned by your system calls is rounded up to a higher degree of precision than the actual CPU clock time. If your ID generation code runs faster than this degree of precision then you will have collision.
  • If your code is distributed and each unit of work is generating ID's then you run into the possibility of ID collision as the separate CPU's or CPU core's allocate ID's using their independent clocks.
  • In libraries like Java that are actually returning the system time based off a user settable property you run into a higher chance of multiple ID collision anytime the date is reset to some period in the past, for whatever reason.

A very good alternative to generating unique identifiers is to utilize the not-so-ironically named Universally Unique Identifier. There is a multiple implementations in various languages, for Java 5 and higher you can use the UUID class.

Edit: To add some useful information about UUID.

Community
  • 1
  • 1
Perception
  • 79,279
  • 19
  • 185
  • 195
  • +1 for "you shouldn't be using time as unique number generator unless you absolutely have to." – Liv Jun 24 '11 at 15:57
  • +1 True, it's better to use a more robust algorithm to generate unique values. What if, for example the application runs on multiple computers, each generating their own values? – Kwebble Jun 24 '11 at 15:59
  • +1 Use UUID, a static counter (single JVM) or a cluster singleton counter (a database or a fancy cluster singleton). – Joshua Davis Jun 25 '11 at 04:57
2

I think your approach is wrong, if this is a requirement.

Theoretically, no matter how fine-grained your timer, a machine might execute it in less time than the timer's granularity. It's not correct in a technical sense to depend on this being true.

Or looking at it another way - why do you need these values to be unique (what are you using them for)? If you really want them to be a measure of the time it was executed, then you ought to be happy that two iterations that happened within the same millisecond got the same value.

Have you considered using a static, monotonous counter to assign IDs to each iteration that are unique within each execution (AtomicLong is great for this)? Something like the following is very easy and has no concurrency issues:

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
}

If you need the timing info and uniqueness, then that's two separate requirements, so why not have a composite key made up of the time and an arbitrary unique ID?

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
  • Yes, the approach is wrong. Neither random numbers nor the system time can guarantee unique numbers. The static counter here will work well for single-JVM systems. It will not work in a cluster. – Joshua Davis Jun 25 '11 at 04:50
1

Similar to @Andrej's solution, but combining a timer and a counter so your numbers shouldn't repeat if you restart your application.

public enum IdGenerator {
    ;

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

    public static long nextId() { return COUNTER.getAndIncrement(); }
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
0

My suggestion

    long id = System.currentTimeMillis();
    for (int i = 0; i < 10; i++) {
        //do your work
        id++;
    }
Pankaj Kumar
  • 21
  • 2
  • 5
0

If you want to still use your method, you could do:

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

Explicitly making your CPU slower.

Marcelo
  • 11,218
  • 1
  • 37
  • 51
0

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

here is a sample outcome

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,
Rafał Rowiński
  • 606
  • 1
  • 11
  • 23
  • Well why not just use Math.random() if all you need is a unique number then? The notion of time has been lost so all you have are (hopefully) unique numbers. – demongolem Jun 25 '11 at 01:53
  • 2
    Basic mathematics: A random number sequence is not the same thing as a unique number sequence. Multiplying by the system time might change the distribution a little, but it's still not unique. – Joshua Davis Jun 25 '11 at 04:53
0

Check out UUID as well...

helios
  • 2,603
  • 4
  • 21
  • 26