`System.currentTimeMillis()` 在多个进程中是否正确? [英] Is `System.currentTimeMillis()` correct across multiple processes?

查看:37
本文介绍了`System.currentTimeMillis()` 在多个进程中是否正确?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个主进程写入日志的情况.

We have a situation where a master process writes to a log.

然后它会产生多个写入自己日志的工作进程.(我想让工人通过 master 登录,但由于某种原因,这个想法遭到了抵制.)

It then spawns multiple worker processes which write to their own logs. (I wanted the workers to log through the master, but there was resistance to this idea for some reason.)

我想知道的是,我能相信最终出现在多个文件中的时间戳是一致的吗?即,如果我将日志文件合并到一个按即时排序的单个文件中,事件的顺序是否为真?跨所有可能的操作系统?

What I want to know is, can I trust that the timestamps that end up in the multiple files are consistent with each other? i.e., if I merge the log files into a single file sorting by instant, will the order of events be true? Across all possible operating systems?

我问这个的原因是我有一个奇怪的情况,在主进程报告工作进程有错误后两秒钟,工作进程似乎记录了一个错误.就好像师父能够预知未来.(我猜主人也是时间领主,但是呃……)

The reason I'm asking this is I have a weird situation where it seems like a worker process has logged an error two seconds after the master has reported that the worker had an error. It's like the master was able to see into the future. (I guess the master is also a time lord, but uh...)

推荐答案

调用 System.currentTimeMillis 及其现代替代品 Instant.now,两者都捕获主机操作系统和底层计算机时钟硬件报告的当前时刻.Javadoc 和源代码承诺基于最佳可用系统时钟"的时钟.

The call to System.currentTimeMillis, and its modern replacement Instant.now, both capture the current moment as reported by the host OS and the underlying computer clock hardware. The Javadoc and source code promise a clock "based on the best available system clock".

所以,不,应该不要跳入未来.每次调用这两种方法时,都会捕捉到当前时刻.

So, no, there should be no jumping into the future. Every time you call either of those methods, you capture the current moment.

但是,您可能会看到跳入未来的错觉.这可能是由于以下原因造成的:

However, you may see the illusion of jumping into the future. This may happen for these reasons:

  • 线程调度
  • 时钟重置
  • 假时钟

这种错觉可能是因为当前时刻被捕获后发生的事情.捕获当前时刻后的瞬间,该线程的执行可能会暂停.其他一些线程可能会捕获稍后的时刻,继续报告那个时刻.最终,第一个线程恢复,并报告其较早捕获的时刻——但请注意该时刻的报告是如何发生的.

This illusion may occur because of what happens after the current moment is captured. The split-second after capturing the current moment, that thread’s execution may be paused. Some other thread may then capture a later moment, continue to report that moment. Eventually, that first thread resumes, and reports its earlier captured moment — but note how the reporting of that moment happens later.

以这个示例代码为例.

package work.basil.example;

import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TellTime
{
    public static void main ( String[] args )
    {
        TellTime app = new TellTime();
        app.demo();
    }

    private void demo ( )
    {
        ExecutorService executorService = Executors.newCachedThreadPool();

        int countThreads = 15;
        List < Callable < Object > > tasks = new ArrayList <>( countThreads );
        for ( int i = 0 ; i < countThreads ; i++ )
        {
            Runnable tellTimeRunnable = ( ) -> System.out.println( Instant.now() );
            tasks.add( Executors.callable( tellTimeRunnable ) );
        }
        try
        {
            List < Future < Object > > list = executorService.invokeAll( tasks );
        }
        catch ( InterruptedException e )
        {
            e.printStackTrace();
        }
    }
}

我第一次运行该代码时,在输出的最后两行中发现了这样的跳转.第 4 行显示比第 3 行早一点.第 5 行显示更早的片刻.

The very first time I ran that code, I found such a jump in the last two lines of output. The 4th line shows a moment earlier than the 3rd. The 5th line shows a moment even earlier.

2020-11-23T01:07:34.305318Z
2020-11-23T01:07:34.305569Z
2020-11-23T01:07:34.305770Z
2020-11-23T01:07:34.305746Z
2020-11-23T01:07:34.305434Z

在我这里的例子中,对 System.out.println 的调用在执行过程中被延迟了,所以一些较早的时刻被稍后报告.同样,我怀疑在您的情况下,记录您捕获的时刻的行为涉及各种延迟,以便稍后记录一些较早的时刻.

In my case here, the calls to System.out.println got delayed in their execution, so some earlier moments were reported later. Likewise, I suspect that in your case, the act of logging your captured moments involved various delays so that some earlier moments were logged later.

正如 Stephen C 指出的那样 在下面的评论中,计算机通常被配置为根据来自时间服务器的信息自动调整硬件时钟.许多计算机中的硬件时钟没有您想象的那么准确.因此,主机的时钟很可能会重置为更早或更晚的时间,以校正时间跟踪漂移.

As Stephen C points out in comments below, computers are often configured to auto-adjust the hardware clock based on info from a time server. The hardware clocks in many computers are less accurate than you might imagine. So the host computer’s clock may well be reset to an earlier or later time-of-day to correct for time-tracking drift.

请注意,某些计算机会将时钟重置回纪元参考点例如 1970-01-01 00:00Z 当使用故障或耗尽的电池/电容器支持硬件时钟启动时.该纪元参考时刻可以被报告为当前时刻,直到计算机有机会与时间服务器签入.

Be aware that some computers reset their clock back to an epoch reference point such as 1970-01-01 00:00Z when booted with a faulty or exhausted battery/capacitor backing the hardware clock. That epoch reference moment may be reported as the current moment until the computer gets a chance to check in with the time server.

或者有人可以手动调整计算机时钟的当前日期和时间.:-(

Or some human could manually adjust the computer clock’s current date and time. :-(

您的代码可能会在此时钟调整的任一侧捕获当前时刻.现在,后来的事件似乎发生得更早了.

Your code may capture the current moment on either side of this clock adjustment. Now a later event may appear to have occurred earlier.

java.time 中,诸如 Instant.now 之类的调用访问当前分配的 Clock 实现.通过当前分配",我指的是在 java.time 中,默认的 Clock 对象可以被覆盖.通常这仅用于测试目的.各种Clock 对象可以报告固定时刻, 一个转变的时刻,或者可以使用 改变节奏.

In java.time, calls such as Instant.now access the currently-assigned Clock implementation. By "currently assigned", I refer to the fact that in java.time, the default Clock object can be overridden. Usually that would be for testing purposes only. Various Clock object can report a fixed moment, a shifted moment, or may report with an altered cadence.

因此请注意,如果您的测试代码指定了替代的 Clock 对象,则替代的 Clock 可能会故意告诉不同的时间.默认情况下,尽管您总是在方法调用执行时获得当前时刻.

So be aware that an alternate Clock may purposely tell a different time, if your testing code specified an alternate Clock object. By default though you always get the current moment at the time that method call executes.

这里有一个主要含义:时间跟踪不能完全信任.当前时刻可能被错误地捕捉,并且捕捉到的时刻的报告可能是乱序的.

There is a major implication here: Time-tracking cannot be completely trusted. The current moment may be incorrectly captured, and the reporting of captured moments may be out-of-order.

因此,在调试或调查时,请始终将这个想法牢记在心:时间戳及其顺序可能不会告诉您全部真相.您最终无法 100% 确定地知道什么时候发生了什么.

So when debugging or investigating, always keep this thought tucked away in the back of your mind: The timestamps and their ordering may not be telling you whole truth. You ultimately cannot know with 100% certainty what happened when.

这篇关于`System.currentTimeMillis()` 在多个进程中是否正确?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆