Tôi cần tạo dấu thời gian (tính bằng mili giây) trong Java được đảm bảo là duy nhất trong cá thể VM cụ thể đó. I E. cần một số cách để điều tiết thông lượng của System.currentTimeMillis() sao cho nó trả về nhiều nhất một kết quả mỗi ms. Bất kỳ ý tưởng về cách thực hiện điều đó?Tạo một dấu thời gian duy nhất trong Java
Trả lời
Điều này sẽ cho thời gian gần thời gian hiện tại nhất có thể mà không có bản sao.
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;
}
}
Một cách để tránh giới hạn một id mỗi milli-giây là sử dụng dấu thời gian vi giây. tức là nhân currentTimeMS vào 1000. Điều này sẽ cho phép 1000 id trên mỗi milli giây.
Lưu ý: nếu thời gian chuyển về phía sau, ví dụ như do hiệu chỉnh NTP, thời gian sẽ chỉ diễn ra ở mức 1 milli giây cho mỗi lần gọi cho đến khi thời gian bắt kịp. ;)
Bạn có thể sử dụng System.nanoTime()
, đây là bộ hẹn giờ hệ thống có sẵn chính xác nhất và chia cho triệu để nhận mili giây. Mặc dù không có bảo đảm chính thức về mức độ thường xuyên cập nhật, tôi tin rằng nó hợp lý để giả định rằng nó cập nhật theo cách nhiều hơn (thứ tự độ lớn) thường xuyên hơn một lần mỗi mili giây. Tất nhiên, nếu bạn tạo dấu thời gian nguyên theo khoảng thời gian nhỏ hơn mili giây, thì chúng không thể là duy nhất.
Lưu ý rằng giá trị tuyệt đối nanoTime()
là tùy ý. Nếu bạn muốn thời gian tuyệt đối, hãy hiệu chỉnh nó theo cách nào đó, tức là so sánh nó với currentTimeMillis()
khi bắt đầu.
Bạn có thể sử dụng System.nanoTime()
cho độ chính xác tốt hơn
Mặc dù tôi đã cố gắng bên dưới và mỗi lần nó mang lại giá trị khác nhau, nó có thể không đảm bảo là duy nhất tất cả các thời gian.
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);
}
Một cách khác là sử dụng AtomicInteger
/AtomicLong
lớp dành cho con số duy nhất nếu thời gian không phải là quan trọng đối với bạn và bạn chỉ cần số duy nhất, điều này có lẽ là một sự lựa chọn btter.
nanoTime là đơn điệu, nhưng không phải lúc nào cũng độc đáo. Bạn có thể nhận được nhiều bản sao. ví dụ. trên Red Hat & Centos 5.x độ phân giải là micro giây, vì vậy bạn nhận được rất nhiều giá trị lặp lại. –
Cảm ơn thông tin. Tôi đoán nó phụ thuộc vào hệ điều hành và máy. – fmucar
Bạn có thể sử dụng nanoTime với một kiểm tra khác biệt của nó. (Tương tự như giải pháp của tôi) nanoTime là thời gian hoạt động trong một giây trên nhiều hệ thống. –
Bạn có thể sử dụng java.util.UUID
và đó là timestamp()
và clockSequence()
?
Method Summary
int clockSequence()
The clock sequence value associated with this UUID.
long timestamp()
The timestamp value associated with this UUID.
Xem thêm chi tiết ở đây: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/UUID.html
Trong khi tìm kiếm một giải pháp tôi đi qua ULIB (Universally Unique thứ tự từ điển Sortable định danh) https://github.com/huxi/sulky/tree/master/sulky-ulid/
Nó không phải là dài, nhưng ngắn hơn sau đó UUID.
Một ULID:
- là tương thích với UUID/GUID của 1.21E + 24 ULIDs độc đáo mỗi millisecond (1,208,925,819,614,629,174,706,176 để được chính xác)
- thứ tự từ điển sắp xếp được
- theo giáo luật mã hóa như là một chuỗi 26 nhân vật, như trái ngược với UUID 36 nhân vật
- Sử dụng base32 Crockford cho hiệu quả tốt hơn và dễ đọc (5 bit mỗi nhân vật)
- Trường hợp không nhạy cảm
- không ký tự đặc biệt (URL an toàn)
tôi không chắc chắn những gì bạn có nghĩa là * throttling * currentTimeMillis() để nó trả về * tối đa là * một kết quả ev ery ms? Nếu bạn muốn dấu thời gian duy nhất, bạn muốn đảm bảo rằng nó trả về một giá trị khác nhau tại mỗi cuộc gọi, phải không? –
Họ có phải tăng đơn điệu không? Họ có phải chịu bất kỳ mối quan hệ nào với thời gian * thực tế không? Chúng có phải là duy nhất trong nhiều lần chạy không? –