I have this realy simple dao operation which works pretty fine(part of a JUnit test):
for (int i = 0 ; i < 5000 ; i++)
mUserDao.saveUser(lUser, new Date().getTime());
the second parameter is a timestamp as long value. I test a kind of bulk save.
my question is: is it theoretical possible that I have two entries with the same long value in my database(mysql)? - in the same process.
A first look inside the relation shows me different long values for each entrie(At least the last millisecond is increased).
Thx in advance
Stefan
You can't guarantee that new Date() will give you the current time accurately. Often it can be wrong by up to about 10ms. Calling new Date() uses System.currentTimeMillis(). The Javadoc for currentTimeMillis() says
Returns the current time in milliseconds. Note that while the unit of time of the return value is a millisecond, the granularity of the value depends on the underlying operating system and may be larger. For example, many operating systems measure time in units of tens of milliseconds.
So it's OS dependent. My experience is that Windows is particularly bad at giving you accurate dates.
And you certainly can't guarantee that you'll get different dates from successive calls to new Date().
Yes this is possible especially if you are having a fast hardware and that two saving operations are done in the same time. Then both created entries will have the same Long value.
I think milliseconds since the UNIX epoch are still the best way to measure time in a reasonably accurate way. However, it's not really good to have a timestamp only as a primary key. As long as you have a unique primary key you don't really need unique timestamps.
In case for some reason you still want the timestamp to be unique, you can apply an 'artificial smear'. For example:
long last = 0;
for (int i = 0 ; i < 5000 ; i++) {
long now = new Date().getTime();
if (now <= last) {
now = last + 1;
}
last = now;
mUserDao.saveUser(lUser, now);
}
There are many ways this can be improved but the code above is just to illustrate the idea of a smear.
Related
Problem situation: I have an incredibly high number of records all marked with a timestamp. I'm looping through all of them to do this and that but I need to detect when the day has changed.
Right now for each loop I'm doing:
cal.setTimeInMillis(record.time);
int currentDay = cal.get(Calendar.DAY_OF_WEEK);
Is this as slow as I imagine it is when it's running hundreds of thousands of times?
I imagine I'm missing a really simple modulo answer or something.
Edit: Time zone does not matter, the information I'm collecting more resolves around a consumable report for someone. 24 hours per report is more accurate, so realistically I don't have to worry about whether or not that's 5am - 5am or 3pm - 3pm, just that I was able to gather 24H worth of info.
Thanks all
After Andy Turner’s time test I am not necessarily convinved that you need any optimized solution. In any case, timsmelik’s suggestion is pretty straightforward: convert the time when the day changes to a count of milliseconds since the epoch so you only need to compare long values. I don’t find that it hurts readability very badly. So here it is in code. I am using and warmly recommending java.time, the modern Java date and time API, if only for the conversion from hours to milliseconds and for printing the results. Even when such a conversion seems trivial, it’s always best to leave to the standard library to do it. It’s more self-explanatory and less error-prone, and it’s easier for the reader to convince oneself that it’s correct.
final long twentyfourHoursAsMillis = Duration.ofHours(24).toMillis();
// Times are already sorted descending (from newest to oldest)
long[] times = { 1_611_718_370_000L, 1_611_632_000_000L,
1_611_631_970_000L, 1_611_459_150_000L };
List<List<Long>> chunks = new ArrayList<>();
List<Long> currentChunk = new ArrayList<>();
// Process first time separately to get started
currentChunk.add(times[0]);
long timeOfNextChunk = times[0] - twentyfourHoursAsMillis;
// Process remaining times
for (int i = 1; i < times.length; i++) {
long currentTime = times[i];
if (currentTime <= timeOfNextChunk) {
chunks.add(currentChunk);
currentChunk = new ArrayList<>();
do {
timeOfNextChunk -= twentyfourHoursAsMillis;
} while (currentTime <= timeOfNextChunk);
}
currentChunk.add(currentTime);
}
// Save last chunk, why not?
chunks.add(currentChunk);
// Print result
for (List<Long> chunk : chunks) {
String chunkAsString = chunk.stream()
.map(Instant::ofEpochMilli)
.map(Instant::toString)
.collect(Collectors.joining(", "));
System.out.println(chunkAsString);
}
Output is:
2021-01-27T03:32:50Z, 2021-01-26T03:33:20Z
2021-01-26T03:32:50Z
2021-01-24T03:32:30Z
I am printing Instant objects. They always print in UTC. For your situation you may want to do otherwise if you need to print the times at all.
You should add a check of your assumption that the times come in sorted order.
I have taken your word for it and broken into chunks at 24 hours. 24 hours may not even mean 5am - 5am but could mean for instance from 5 AM EST on March 13 to 6 AM EDT on March 14 because summer time (DST) has begun in the meantime. If you prefer to split at the same clock hour, the code can be modified to do that.
I want to attach a timestamp whenever an event happens in my application. Let's assume that a client creates a Event object and I want to attach a creation timestamp to the Event object. I can do this using the System.currentTimeMillis() within the constructor. This works fine if the Event objects are created no faster than once every millisecond. In this case each Event object gets a different value from System.currentTimeMillis() and hence the Event objects are sequenced.
However if the Event objects need to be created a rate that is faster than one object per millisecond, then my logic breaks. Depending on the rate of object creation 2 or more Event objects end up having the same creation timestamp (since System.currentTimeMillis returned the same value when called in quick succession)
Now how do I sequence the Event objects in this case? I am aware of the System.nanoTime() but that's not related to the epoch.
I am open to storing the creation timestamp within the Event class split into 2 instance variables - creationTimeInMS (long) and creationTimeInNS (long)
I do not want to java.sql.Timestamp which does support nano second precision
Is there anyway I could leverage the System.nanoTime to provide sequencing of the event objects?
Note - It is guaranteed that the event will not get created faster than 1 per nanosecond. Hence nanosecond precision will suffice
The code that I have using is as below
class Event {
private long timestamp
public Event() {
...
timestamp = System.currentTimeMillis()
}
So if the Event constructor is called by multiple threads at a rate faster than 1 per millisecond, then two (or more) Event objects get the same timestamp.
The System.nanoTime() is supposed to return unique number if called no faster than once every nano second. However I am not sure how I could use this number in conjunction with the timestamp. Do I add this to the timestamp to generate a nano second precision time?
It is hard to achieve that with relying on the wall clock, times are gonna collide and nano second resolution is hard to achieve in practice, a quick solution is to add a wrapper around the time that remembers its last value. This wont work in a distributed environment of course.
static class MonotonicClock{
private long last;
public MonotonicClock(){
last = System.currentTimeMillis();
}
public synchronized long getNext(){
long current = System.currentTimeMillis();
if(last < current){ // last seen is less than "now"
last = current;
}else{
last++; //collision, overclock the time
}
return last;
}
}
In a distributed system, things are more complicated. You might need to look at Lamport timestamps and Vector Clocks for that.
I need to create a 64 bit unique integer in Java so that collision chances are low. The system is not distributed, so collisions between different computers are not a problem.
Is there any way, we can create a 64 bit integer in Java which is always Unique?
As of now I am using -
long number = System.nanoTime();
Is this the right way to generate 64 bit Unique Integer in Java or is there anything else I can try?
UPDATE:-
How about doing this way? Will this be unique?
UUID number = UUID.randomUUID();
long uniqueNumber = number.timestamp();
If you need the numbers to be unique in one process, robust between restarts, you can use a simple AtomicLong and a timer.
private static final AtomicLong TS = new AtomicLong();
public static long getUniqueTimestamp() {
long micros = System.currentTimeMillis() * 1000;
for ( ; ; ) {
long value = TS.get();
if (micros <= value)
micros = value + 1;
if (TS.compareAndSet(value, micros))
return micros;
}
}
This will give you a unique "timestamp" with a millisecond accuracy but can only handle 1000 ids per millisecond without getting ahead of the actual time. This works fine on restart as the time will jump past previous values (again assuming you have less than one million per second on average)
Use a HashSet in order to ensure uniqueness of the values you're storing. You can then check whether the insert was successful by checking what add returns. If the values have to be 'randomised' you can use your own algorithm, or check out SecureRandom.
Long getUniqueNumber(HashSet uniqueNumberSet) {
Long unique = generateUniqueNumber();
if(!uniqueNumberSet.add(unique)) { // handle collision }
return unique;
}
As Marc B said, the best approach is a simple long which is initialized with zero and incremented every time you need a new value.
If you need concurrency, or if performance is not an issue at all, then you can use AtomicLong as suggested by Loc Ha; however, if you really need it to be a long and not an int, then I suspect you are going to be generating lots of them, so you should probably avoid the extra overhead of AtomicLong unless you are sure you also need concurrency.
System.nanoTime() is not a good idea, as you have no guarantee that two consecutive calls to it will always yield different values.
EDIT (to cover update in question)
No, the timestamp part of the UUID is not guaranteed to be unique, for precisely the same reasons that System.nanoTime() is not guaranteed to be unique. If the timestamp of the UUID was unique, then there would be no need to have a UUID type, we would just always use that timestamp part. Time is always a bad way to go about guaranteeing uniqueness.
You want to get unique ID, the appropriate way(although 128 bit):
UUID.randomUUID();
A bit less appropriate(collisions* are possible) with 64 bits:
UUID.getLeastSignificantBits();
UUID.getMostSignificantBits();
To really get unique ID(if they are critical to your operation):
Use centralised storage of all IDs
When you need an ID, let this centralised system handle it -> DB and auto incremented values are usually the easiest way
*collisions => 2 or more equal values
I am making a call to a method by passing ipAddress and it will return back the location of ipAddress like Country, City, etc etc. So I was trying to see how much time it is taking for each call. So I set the start_time before making call to method and end_time after making a call. So sometimes I get difference as 0. And resp contains the valid response.
long start_time = System.currentTimeMillis();
resp = GeoLocationService.getLocationIp(ipAddress);
long end_time = System.currentTimeMillis();
long difference = end_time-start_time;
So that means sometimes it is taking 0 ms to get the response back. Any suggestions will be appreciated.
Try this
long start_time = System.nanoTime();
resp = GeoLocationService.getLocationByIp(ipAddress);
long end_time = System.nanoTime();
double difference = (end_time - start_time) / 1e6;
I pretty much like the (relatively) new java.time library: it's close to awesome, imho.
You can calculate a duration between two instants this way:
import java.time.*
Instant before = Instant.now();
// do stuff
Instant after = Instant.now();
long delta = Duration.between(before, after).toMillis(); // .toWhatsoever()
API is awesome, highly readable and intuitive.
Classes are thread-safe too. !
References: Oracle Tutorial, Java Magazine
No, it doesn't mean it's taking 0ms - it shows it's taking a smaller amount of time than you can measure with currentTimeMillis(). That may well be 10ms or 15ms. It's not a good method to call for timing; it's more appropriate for getting the current time.
To measure how long something takes, consider using System.nanoTime instead. The important point here isn't that the precision is greater, but that the resolution will be greater... but only when used to measure the time between two calls. It must not be used as a "wall clock".
Note that even System.nanoTime just uses "the most accurate timer on your system" - it's worth measuring how fine-grained that is. You can do that like this:
public class Test {
public static void main(String[] args) throws Exception {
long[] differences = new long[5];
long previous = System.nanoTime();
for (int i = 0; i < 5; i++) {
long current;
while ((current = System.nanoTime()) == previous) {
// Do nothing...
}
differences[i] = current - previous;
previous = current;
}
for (long difference : differences) {
System.out.println(difference);
}
}
}
On my machine that shows differences of about 466 nanoseconds... so I can't possibly expect to measure the time taken for something quicker than that. (And other times may well be roughly multiples of that amount of time.)
Since Java 1.5, you can get a more precise time value with System.nanoTime(), which obviously returns nanoseconds instead.
There is probably some caching going on in the instances when you get an immediate result.
From Java 8 onward you can try the following:
import java.time.*;
import java.time.temporal.ChronoUnit;
Instant start_time = Instant.now();
// Your code
Instant stop_time = Instant.now();
System.out.println(Duration.between(start_time, stop_time).toMillis());
//or
System.out.println(ChronoUnit.MILLIS.between(start_time, stop_time));
I do not know how does your PersonalizationGeoLocationServiceClientHelper works. Probably it performs some sort of caching, so requests for the same IP address may return extremely fast.
In the old days (you know, anytime before yesterday) a PC's BIOS timer would "tick" at a certain interval. That interval would be on the order of 12 milliseconds. Thus, it's quite easy to perform two consecutive calls to get the time and have them return a difference of zero. This only means that the timer didn't "tick" between your two calls. Try getting the time in a loop and displaying the values to the console. If your PC and display are fast enough, you'll see that time jumps, making it look as though it's quantized! (Einstein would be upset!) Newer PCs also have a high resolution timer. I'd imagine that nanoTime() uses the high resolution timer.
In such a small cases where difference is less than 0 milliseconds you can get difference in nano seconds as well.
System.nanoTime()
You can use
System.nanoTime();
To get the result in readable format, use
TimeUnit.MILLISECONDS or NANOSECONDS
I need to create a timestamp (in milliseconds) in Java that is guaranteed to be unique in that particular VM-instance. I.e. need some way to throttle the throughput of System.currentTimeMillis() so that it returns at most one results every ms. Any ideas on how to implement that?
This will give a time as close the current time as possible without duplicates.
private static final AtomicLong LAST_TIME_MS = new AtomicLong();
public static long uniqueCurrentTimeMS() {
long now = System.currentTimeMillis();
while(true) {
long lastTime = LAST_TIME_MS.get();
if (lastTime >= now)
now = lastTime+1;
if (LAST_TIME_MS.compareAndSet(lastTime, now))
return now;
}
}
One way to avoid the limitation of one id per milli-second is to use a micro-second timestamp. i.e. multiply currentTimeMS by 1000. This will allow 1000 ids per milli-second.
Note: if time goes backwards, eg due to an NTP correction, the time will just progress at 1 milli-second per invocation until time catches up. ;)
You can use System.nanoTime() for better accuracy
Although I tried below and each time it gives different values, it probably is not guaranteed to be unique all the time.
public static void main(String[] args) {
long time1 = System.nanoTime();
long time2 = System.nanoTime();
long time3 = System.nanoTime();
System.out.println(time1);
System.out.println(time2);
System.out.println(time3);
}
Another way is to use AtomicInteger/AtomicLong classes for unique numbers if the time is not important for you and you just need unique number, this probably is a btter choice.
While searching for a solution I came across ULIB
(Universally Unique Lexicographically Sortable Identifier)
https://github.com/huxi/sulky/tree/master/sulky-ulid/
It's not a long, but shorter then UUID.
A ULID:
Is compatible with UUID/GUID's
1.21e+24 unique ULIDs per millisecond (1,208,925,819,614,629,174,706,176 to be exact)
Lexicographically sortable
Canonically encoded as a 26 character string, as opposed to the 36 character UUID
Uses Crockford's base32 for better efficiency and readability (5 bits per character)
Case insensitive
No special characters (URL safe)
You could use System.nanoTime(), which is the most precise available system timer, and divide that by million to get milliseconds. While there are no formal guarantees on how often it's updated, I believe it's reasonable to assume that it updates way more (order(s) of magnitude) frequently than once per millisecond. Of course, if you create integer timestamps by less than millisecond interval, then they can't all be unique.
Note that the absolute value nanoTime() is arbitrary. If you want absolute time, calibrate it somehow, i.e. compare it to currentTimeMillis() when starting.
Could you perhaps make use of java.util.UUID and it's timestamp() and clockSequence()?
Method Summary
int clockSequence()
The clock sequence value associated with this UUID.
long timestamp()
The timestamp value associated with this UUID.
More details here: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/UUID.html