Editor PHP Apple akan menerangkan sebab masa berlalu yang dikira pada tetingkap masa yang besar mempunyai perbezaan sehingga 100+ milisaat antara System.currentTimeMillis dan System.nanoTime. Isu ini melibatkan mekanisme asas sistem komputer dan kaedah penjadualan sistem pengendalian. Apabila mengira masa berlalu, System.currentTimeMillis menggunakan masa jam dinding yang disediakan oleh sistem pengendalian, manakala System.nanoTime menggunakan kitaran jam CPU. Disebabkan oleh mekanisme penjadualan sistem pengendalian dan sifat tak segerak jam perkakasan, kedua-dua kaedah pemasaan ini akan menyebabkan perbezaan masa. Sebab dan penyelesaian khusus akan diperkenalkan secara terperinci dalam artikel berikut. kandungan soalan dikira sebagai bilangan mikrosaat berlalu sejak kali pertama seketika, dan nilai bermula pada kali kedua seketika. Gunakan masa berlalu yang dikira daripada masa nano dan tambahkannya pada milisaat segera awal supaya kita boleh mengira zaman dengan ketepatan mikrosaat pada bila-bila masa selepas jvm bermula (semuanya dalam jvm yang sama).
//Mulai dari sini, apabila masa semasa dengan ketepatan mikro/nanosaat diperlukan, hitung masa berlalu daripada masa nano dan tambah milisaat berlalu kepada initialmillis, dan masa berlalu selebihnya memberikan masa dengan ketepatan mikrosaat
最终长 inittimenanos = system.nanotime();最终长 inittimemillis = system.currenttimemillis();
//Monotoni meningkatkan cap waktu milisaat sejak jvm bermula (zaman, kami mungkin tidak memanggilnya zaman)
//Ketepatan masa tambahan daripada nanotimefinal long elapsednanotime = system.nanotime() - inittimenanos;最终双精度 elapsedmillisfromnanotime = elapsednanos / (1000000.0);
final 长计算当前时间millis = inittimemillis + elapsedmillisfromnanotime; final long nanosprecision = elapsednanos % 1000000;
//Perbezaan masa berlalu
Adakah saya terlepas apa-apa tentang jaminan pemasaan jvm, adakah cara pengiraan cap masa anggaran meningkat secara monoton salah? (Ini tidak digunakan sebagai zaman sebenar dalam sistem, hanya untuk menjana uuid yang juga mewakili anggaran cap waktu segera dalam jvm yang sama). final long elapsedmillis = system.currenttimemillis() - inittimemillis;
最终双方差millis = elapsedmillisfromnanotime - elapsedmillis;
// Kelas ujian
package org.example; import java.util.concurrent.TimeUnit; public class Main { public static void main(String[] args) throws Exception { final long initTimeNanos = System.nanoTime(); final long initTimeMillis = System.currentTimeMillis(); System.out.println("Nanos: " + initTimeNanos); System.out.println("Millis: " + initTimeMillis); while (true) { final long currentNanos = System.nanoTime(); final long elapsedNanos = currentNanos - initTimeNanos; final double elapsedMillisFromNanos = elapsedNanos / 1000000.0; final long elapsedMillis = System.currentTimeMillis() - initTimeMillis; final double varianceMillis = elapsedMillisFromNanos - elapsedMillis; if (Math.abs(varianceMillis) > 1) { System.out.printf("\nVariance Observed: %.6f\n", varianceMillis); System.out.printf("Elapsed Time: %.6fms (from System.nanoTime)\n", elapsedMillisFromNanos); System.out.printf("Elapsed Time: %dms (from System.currentTimeMillis)\n", elapsedMillis); } if (elapsedMillis > TimeUnit.HOURS.toMillis(48)) { break; } Thread.sleep(5000); System.out.print("."); } } }
Mengapa varians masa berlalu terus berubah? Apakah varians maksimum yang boleh kita jangkakan jika jvm berjalan secara berterusan selama setahun (mana-mana jvm menjamin sempadan atas atau bawah pada ini, diuji dengan mac dan windows, mac memberikan peningkatan yang perlahan dalam varians, tingkap adalah lebih cepat) ?
Saya menjangkakan masa berlalu berubah kurang daripada 10 milisaat dan perubahan berlaku kurang kerap. Tetapi pemerhatian sebenar adalah bahawa varians terus berubah, turun naik naik dan turun, dengan sehingga 150 milisaat diperhatikan dalam masa 48 jam
Penyelesaian
Satu penjelasan ialah calitan masa berdasarkan ntp. Secara umumnya, masa nano dan ctm mengukur perkara yang sama sekali berbeza dan anda tidak boleh mencampurkannya.
system.ctm mendapat jam sistem. Jika anda menggunakan posix
apa yang dikembalikan. ctm juga secara amnya jauh lebih perlahan daripada masa nano. ctm juga mempunyai 0 yang jelas - mewakili UTC tengah malam 1 Januari 1970.Soalan: "Saya mahu masa semasa sepadan dengan jam sistem dengan ketepatan nanosaat" adalah
tidak mungkindate
命令或在系统设置中编辑系统的时间设置,则不会影响 nanotime
,但会更改 system.ctm
pada jvm.
时间涂抹是指某些网络时间守护程序注意到您的系统时钟略有偏差,并且不只是将系统时钟编辑到正确的时间,而是引入了涂抹:假设您比实时时间“提前”了 400 毫秒。 ntp 可以将您的时钟向后设置 400 毫秒,但许多日志记录系统假设 system.ctm 不会向后移动(这是一个不正确但广泛应用的假设)。
这可以通过让时间放慢一段时间来“修复”:每经过 100 毫秒,ntp 守护进程就会将时钟“保持”在同一毫秒上一毫秒。每 100 毫秒就赶上 1 毫秒,因此在 400,000 毫秒(仅 400 秒)内,时钟恢复与网络同步,并且日志记录根本不受影响。
但是,这显然会完全破坏 system.ctm 和 nanotime 之间的任何关系!
大多数 ntp 都是这样涂抹的(它们也会向前涂抹 - 如果您的系统时钟落后,它不仅仅会向前跳跃:这会使日志撒谎(使其看起来就像两个事件之间存在一些间隙)比实际大得多),因此每 100 毫秒,ntp 就会使时钟跳过一毫秒,类似这样的事情,以赶上。
那么 nanotime 就无关紧要了。不要使用它。
拥有一些提供 id 的集中“商店”。一种实现:
class TimeStore { long lastVal = 0L; public synchronized long get() { long mark = System.currentTimeMillis() << 4; return lastVal = Math.max(mark, lastVal + 1); } }
这将返回当前时间,左移 4 位,并将填充此移位“释放”的 16 个值,以便能够在同一时间生成单调递增值,最多 16 次;同一毫秒内的任何进一步请求都会潜入下一毫秒。
尽管如此,这可能并不比nanotime慢。
rzwitserloot的回答是正确的。我将向您提供我对各种问题的看法。
currenttimemillis
与 nanotime
无关system.currenttimemillis
和 system.nanotime
彼此无关。
currenttimemillis
从主机的硬件时钟单元检索当前日期和时间,由主机操作系统管理。nanotime
来自主机 cpu 保存的计数。currenttimemillis
所以首先要了解人类的年月日和时分秒的概念。传统计算机中使用的时钟硬件的分辨率有限,有些是毫秒,有些是微秒,但没有纳秒。
由于各种原因,本次通话报告的日期和时间可能会有所不同。其中一个原因是,在电池电量耗尽的情况下启动的计算机会将其时钟重置为默认时刻,直到通过调用时间服务器进行纠正。另一个原因是系统管理员或用户可能会更改日期时间。还有一个原因是硬件时钟可能无法很好地保持时间,并且会通过调用时间服务器在更新之间运行得快或慢。
nanotime
nanotime
调用以纳秒计数形式告知经过的时间。但这个流逝的时间与日历和墙上的时钟无关。此调用仅返回经过的纳秒的单调计数。
这个计数非常准确,因为它来自计算机的“跳动的心脏”。返回的数量始终在增加,直到达到 long.max_value
,然后环绕到 long.min_value
。这给出了大约 292 年的范围,但这并不意味着从现在起 292 年。计数的起点未指定。在某些 java 实现中,您可能会看到计数在计算机启动时开始。但并不能保证这一点。
您可能会考虑寻找 新 6、7、8 版本 的实现a href="https://en.wikipedia.org/wiki/universally_unique_identifier" rel="nofollow noreferrer">uuid 被提议给 ietf 进行标准化。
currenttimemillis 在现代 java 中已被 java.time.instant
类取代。调用 instant.now
捕获 utc 中的当前时刻。
java 9+ 中的常见实现以微秒为单位报告,但在 java 8 中以毫秒为单位。 instant
类能够以纳秒为单位。
Idea bijak. Tetapi ia tidak realistik. Seperti yang dinyatakan di atas, currenttimemillis
和 nanotime
不相关。最重要的是,currenttimemillis
的结果可能会因多种原因而有所不同。同时,nanotime
计数可能会随着主机的每次启动而变化,并且肯定不会对应于其他计算机上进行的任何 nanotime
panggilan.
Ya, anda mengabaikan fakta bahawa spesifikasi java tidak membuat sebarang jaminan yang anda seolah-olah andaikan.
Satu-satunya jaminan dalamjavadoc ialah nanotime
是“高分辨率”,至少与 currenttimemillis
adalah sama baiknya. Dan tiada jaminan apabila anda boleh menjangkakan penghujung 292.
Pada masa yang sama, currenttimemillis
ialah sasaran yang bergerak dan boleh berubah pada bila-bila masa, bergerak ke hadapan atau ke belakang.
Ia tidak dapat diramalkan.
Spesifikasi Java tidak memberikan jaminan sedemikian.
Atas ialah kandungan terperinci Mengapakah masa berlalu dikira dalam tetingkap masa yang besar berbeza sehingga 100+ milisaat antara System.currentTimeMillis dan System.nanoTime. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!