java for loop executes too fast gives System.curre

2019-05-14 17:11发布

问题:

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()

回答1:

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



回答2:

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



回答3:

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?



回答4:

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.



回答5:

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


回答6:

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.



回答7:

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,


回答8:

Check out UUID as well...



回答9:

My suggestion

    long id = System.currentTimeMillis();
    for (int i = 0; i < 10; i++) {
        //do your work
        id++;
    }