• Post Reply Bookmark Topic Watch Topic
  • New Topic

currentTimeMillis as UniqueIDGenerator  RSS feed

 
Shridhar Raghavan
Ranch Hand
Posts: 71
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

I wanted to explore various patterns to generate a unique long value. I had a few queries regarding currentTimeMilllis with this regard. First what exactly does the api mean when it says the actual granularity of the return value is OS dependent. Do they mean to say my Mac does not time 1ms as the standard 1ms and instead evaluates 1-2 ms in real time as it's 1ms. Or are they suggesting that it isnt precise?

Now with this mind, what are the limitations of unique currentTimeMillis as a standlone unique id generator? Should i club it with somthing more unique like a mac address or something. Any other suggestions?
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Shridhar Raghavan wrote:Do they mean to say my Mac does not time 1ms as the standard 1ms and instead evaluates 1-2 ms in real time as it's 1ms. Or are they suggesting that it isnt precise?

I'd suggest that, for your purposes, the two things are the same.

Now with this mind, what are the limitations of unique currentTimeMillis as a standlone unique id generator? Should i club it with somthing more unique like a mac address or something.

The limitations are exactly what you've already observed. My clunky old Dell can create roughly 100 million Objects a second, and even if you don't get that sort of performance with your own classes, you will probably be able to create them very quickly indeed. A MAC address (if you can obtain it easily) might not be a bad idea if the ID needs to span more than one machine, but it still won't change the fact that you could create several objects in the same clock tick on the same machine.

Any other suggestions?

Yes. Have a look at java.util.UUID.

Alternatively, an object containing 2 longs:
1. System.currentTimeMillis();
2. Random.nextLong();
is likely to be pretty unique too.

Winston
 
Hunter McMillen
Ranch Hand
Posts: 492
Firefox Browser Linux VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
just returns the current count of milliseconds since midnight, January 1, 1970. It gets this number from the underlying OS. In some OS'es the OS doesn't update the millisecond count every millisecond, but might do it every 10,20, or 40 milliseconds because that is just how the OS designers chose to group time.

It may not be the best idea to generate IDs using this method, since there is no way of guaranteeing that it will work the same on multiple operating systems.

Alternate Solution:
Is there something wrong with having a start ID of 1 and increment that ID every time to assign one?


Hope this helps,
Hunter
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hunter McMillen wrote:Is there something wrong with having a start ID of 1 and increment that ID every time to assign one?

Not unless the ID needs to be unique across JVM sessions. I presume this may not be enough since Shridhar already asked about MAC addresses.

Winston
 
Hunter McMillen
Ranch Hand
Posts: 492
Firefox Browser Linux VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:
Not unless the ID needs to be unique across JVM sessions. I presume this may not be enough since Shridhar already asked about MAC addresses.

Winston


That would be true, but it seemed to me that MAC addresses only got mentioned because of their uniqueness.

Hunter
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hunter McMillen wrote:That would be true, but it seemed to me that MAC addresses only got mentioned because of their uniqueness.

Yes, but a simple sequence would repeat between JVM sessions. If the ID needs to be saved, I suspect that won't be enough.

Winston
 
Bear Bibeault
Author and ninkuma
Marshal
Posts: 66306
152
IntelliJ IDE Java jQuery Mac Mac OS X
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If a database is involved, a sequence might serve the purpose.
 
Jesper de Jong
Java Cowboy
Sheriff
Posts: 16060
88
Android IntelliJ IDE Java Scala Spring
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There are many reasons why System.currentTimeMillis() is not suitable as a unique ID generator:
  • Any modern computer can generate millions of objects in a millisecond. So System.currentTimeMillis() is too slow - it can generate only at most 1000 values per second (1 ms = 1/1000 second).
  • If your program is multi-threaded and you have a multi-core CPU, then different cores might be creating objects at the same time. So an ID generator based solely on the current time cannot guarantee unique values.
  • If the system clock is adjusted (many computers synchronize the clock via an Internet time service, for example), then it is possible that for a while the same values are generated.

  •  
    Shridhar Raghavan
    Ranch Hand
    Posts: 71
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Any modern computer can generate millions of objects in a millisecond. So System.currentTimeMillis() is too slow.
    While speed in this context is an issue i can work around this by creating a large enough set of row ids before catering to any request right?
    If your program is multi-threaded and you have a multi-core CPU, then different cores might be creating objects at the same time
    Can i work around this using thread synchronisation and separate the row id generation routines from being thread aware? I mean when a new thread is spawned, each thread does not create a new row id, but rather fetches a row id from a collection of possible values. This fetching can be thread safe and the creation process of row ids can be separated.
    If the system clock is adjusted
    This is problematic. Will think on this. Any comments on the above?


     
    Shridhar Raghavan
    Ranch Hand
    Posts: 71
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi,

    Could someone clarify the doubts I raised.
     
    Winston Gutkowski
    Bartender
    Posts: 10575
    66
    Eclipse IDE Hibernate Ubuntu
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Shridhar Raghavan wrote:Hi,
    Could someone clarify the doubts I raised.

    I don't see any doubts, I see unknowns. Do you want a row id (ie, an identifier to a database row), or a unique identifier for a Java object? The two are NOT the same.

    As far as the first is concerned, you don't have to worry about Threads; the database will handle it. As for the second, did you look at UUID, as I suggested in my first post? Again, with it, Threads should not be a concern, since the likelihood of two Threads producing the same UUID is virtually impossible (but NOT 0).

    You also haven't answered the question whether this ID is supposed to be unique across machines. Again, the chances are that a UUID will be unique that way too, but the probability of collision goes up with the number of machines (you'd still have to have several hundred before "virtually impossible" becomes "almost impossible" though).

    Winston
     
    Shridhar Raghavan
    Ranch Hand
    Posts: 71
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi,

    First i desire to persist a long row id in the database and not an object identifier. Secondly, at present i do not foresee requiring the id to be unique across machines. But rather than exploit sequences by the databases i would like to write a unique id generation algorithm. So i was searching for mechanisms to achieve that using present tools.
     
    Winston Gutkowski
    Bartender
    Posts: 10575
    66
    Eclipse IDE Hibernate Ubuntu
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Shridhar Raghavan wrote:First i desire to persist a long row id in the database and not an object identifier.

    Again, I'm not quite sure what you mean here. A database uses a row id to uniquely identify a database row. It may or may not give you explicit access to it; you'd need to read the documentation. If you mean a unique identifier to a row in a table (eg, for use as a primary key) then there are two basic possibilities:
    1. An existing identifier (eg, National ID number, SKU, IBAN or Barcode) produced according to written specifications.
    2. A sequence number.

    Secondly, at present i do not foresee requiring the id to be unique across machines. But rather than exploit sequences by the databases i would like to write a unique id generation algorithm. So i was searching for mechanisms to achieve that using present tools.

    Then I would definitely suggest a UUID. It is a class designed to do precisely what you want, and uses an established written standard (RFC 4122) to do it. Furthermore, it is time-based (which was one of your original concerns) and already provides practical certainty of uniqueness across machines. Because of this, it is also Thread-safe.

    Winston

    Edit: Having looked at the API for version 7, UUID still doesn't appear to have an automated method for generating time-based UUIDs, so you'll have to create them yourself (the algorithm is described in the RFC). Alternatively, there are 3rd party libraries (eg, JUG) that will do it, or you can use the randomUUID() factory to generate a random one.
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!