2010-06-05 28 views
39

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html#currentTimeMillis() nói:Liệu System.currentTimeMillis luôn trả về một giá trị> = cuộc gọi trước đó?

Trả về thời gian hiện tại tính bằng mili giây. Lưu ý rằng mặc dù đơn vị thời gian của giá trị trả lại là một phần nghìn giây, độ chi tiết của giá trị phụ thuộc vào hệ điều hành cơ bản và có thể lớn hơn. Ví dụ, nhiều hệ điều hành đo thời gian theo đơn vị hàng chục mili giây.

Không rõ ràng với tôi nếu tôi được đảm bảo rằng mã này sẽ luôn in với số lượng ngày càng tăng (hoặc giống nhau).

while (1) { 
    System.out.println(System.currentTimeMillis()); 
} 
+0

Vui lòng xem xét trích dẫn một liên kết gần đây hơn. – trashgod

+4

FYI - cách chính xác để đặt câu hỏi này là liệu 'currentTimeMillis' là * đơn điệu *. –

+2

Về mặt kỹ thuật, nó tăng lên một cách đơn điệu. Các hàm đơn điệu có thể tăng hoặc giảm. –

Trả lời

45

Câu trả lời ngắn gọn là không, System.currentTimeMillis()không đơn điệu. Nó dựa trên thời gian hệ thống và do đó có thể chịu sự thay đổi theo cách (chuyển tiếp hoặc lùi) trong trường hợp điều chỉnh đồng hồ (ví dụ: qua NTP).

System.nanoTime() là đơn điệu, nếu và chỉ khi nền tảng cơ bản hỗ trợ CLOCK_MONOTONIC - hãy xem các nhận xét trên Java bug report 6458294 để có ghi chú tốt về một số trường hợp điều này là đúng/không đúng.

(Và, như một giai thoại bổ sung, tôi đã quan sát cá nhân (nhiều lần) System.currentTimeMillis() chạy 'ngược', trong trường hợp không có điều chỉnh đồng hồ, qua chủ đề - tức là, một cuộc gọi đến phương thức đó trong một chuỗi trả về giá trị thấp hơn so với cuộc gọi trong chuỗi khác, mặc dù nó xảy ra theo thứ tự thời gian sau chuỗi trong 'thời gian thực')

Nếu bạn cần nguồn đơn điệu, System.nanoTime() trên nền tảng hỗ trợ đơn điệu là lựa chọn tốt nhất của bạn.

+0

+1 Thông tin. Bạn sẽ giải thích về cách bạn "cá nhân quan sát" 'currentTimeMillis()' để chạy ngược? Điều này trông giống như một doanh nghiệp khá phức tạp, và Heisenberg đến với tâm trí. Bạn đã đồng bộ hóa chủ đề của mình chưa? Và vẫn có thể quan sát thời gian chạy ngược? –

+2

Phiên bản đơn giản là chúng tôi đã có một số công việc thời gian đã lưu trữ 'long start = System.currentTimeMillis()', và sau đó bắn ra một luồng khác để thực hiện công việc, chính nó đã làm 'long end = System.currentTimeMillis()' ở cuối và trừ hai. Sự khác biệt này (không phổ biến) tiêu cực trong trường hợp các công việc rất ngắn. Điều này làm tôi bối rối cho đến khi tôi thực hiện một số nghiên cứu và đào sâu vào mã. :) – Cowan

+0

Vì vậy, luồng # 1 đã làm 'long startInCallingThread = Sys.cTM()' và chuyển giá trị đó cho luồng # 2, mà sẽ nhận được các giá trị âm cho 'Sys.cTM() - startInCallingThread'? Hấp dẫn. Có lẽ bạn đang chạy nó trong một máy ảo? Và bởi * vắng mặt của điều chỉnh đồng hồ *, bạn có nghĩa là chỉ điều chỉnh thủ công hay điều này cũng sẽ bao gồm điều chỉnh tự động, giống như những điều gây ra bởi một daemon ntp? –

8

Nó không thể nào đảm bảo được tăng lên, dựa trên thực tế là người dùng có khả năng có thể thay đổi thời gian hệ thống giữa các cuộc gọi.

Bên cạnh đó, nó nên tiếp tục tăng vì nó đại diện cho mili giây kể từ thời đại. Nếu đó là một "thời gian tường" bình thường, bạn sẽ phải lo lắng về những thay đổi về thời gian trong ngày nhuận hoặc chuyển đổi tiết kiệm ánh sáng ban ngày.

+1

Trong thực tế, nó được đảm bảo định kỳ. Khoảng 292.277.020 năm, nó sẽ in một số lượng cực lớn theo sau là một số cực kỳ nhỏ. – emory

1

@Mark Rushakoff là đúng; nanoTime() có thể đáng tin cậy hơn một chút.

Phụ lục: lưu ý những điều này caveats, được trích dẫn bởi @Steven Schlansker.

+2

Hãy lưu ý điều này mặc dù: http://stackoverflow.com/questions/510462/is-system-nanotime-completely-useless –

+0

@Steven Schlansker: Cảm ơn, tham khảo tốt. – trashgod

11

Không, nó sẽ không luôn luôn là> = tất cả các cuộc gọi trước đó.

  • Nó có thể không tăng mỗi lần nếu bạn gọi nó nhiều lần liên tiếp nhanh chóng từ cùng một sợi (Tôi biết đây là một phần của => =, nhưng hành vi này thường mọi người ngạc nhiên).

  • Nếu bạn gọi nó vài lần liên tiếp nhanh chóng từ nhiều luồng, nó có thể làm bất kỳ số thứ gì - nó có thể hơi quay ngược thời gian qua các chủ đề với số lượng rất nhỏ, tùy thuộc vào việc triển khai và ngẫu nhiên.

  • Quan trọng nhất, giá trị có thể quay trở lại đúng thời hạn bởi số lượng lớn nếu người dùng (hiếm) hoặc đồng bộ hóa NTP (có thể phổ biến) điều chỉnh đồng hồ hệ thống.

7

Nếu bạn muốn một giá trị tăng đều đơn điệu, bạn có thể làm điều gì đó tương tự.

public enum Time { 
    ; 
    private static long lastTime; 
    public synchronized static long increasingTimeMillis() { 
     long now = System.currentTimeMillis(); 
     if (now > lastTime) 
      return lastTime = now; 
     return ++lastTime; 
    } 
} 

Miễn là bạn gọi số này ít hơn một nghìn lần mỗi giây, thời gian tăng của bạn sẽ không trôi quá xa thời gian thực nhưng sẽ là duy nhất. (Điều này có thể hoạt động, ngay cả khi bạn khởi động lại ứng dụng của mình)

Các vấn đề liên quan