【问题标题】:Is this the proper way to time concurrent threads in Java这是在Java中计时并发线程的正确方法吗
【发布时间】:2015-09-23 22:13:43
【问题描述】:

我需要计算运行我编写的应用程序的每个线程所需的时间,并且我已经完成并得到了结果,但实际上并没有任何好的方法来验证我是否做对了。我以前从来没有做过这样的事情。如果有人可以给我一个快速校对,那将非常有帮助。

这是创建线程的代码:

for (int i = 0; i < ROWS; i++) {
    threads[threadCount] = new Thread(new TextDistanceThread("Macbeth.txt", "Othello.txt", i, 0));
    threads[threadCount++].start();
    threads[threadCount] = new Thread(new TextDistanceThread("Macbeth.txt", "HuckFinn.txt", i, 1));
    threads[threadCount++].start();
    threads[threadCount] = new Thread(new TextDistanceThread("Macbeth.txt", "TomSawyer.txt", i, 2));
    threads[threadCount++].start();
    threads[threadCount] = new Thread(new TextDistanceThread("Othello.txt", "HuckFinn.txt", i, 3));
    threads[threadCount++].start();
    threads[threadCount] = new Thread(new TextDistanceThread("Othello.txt", "TomSawyer.txt", i, 4));
    threads[threadCount++].start();
    threads[threadCount] = new Thread(new TextDistanceThread("TomSawyer.txt", "HuckFinn.txt", i, 5));
    threads[threadCount++].start();
}

以及线程本身的代码:

public void run() {

    long start = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime();

//DO SOME STUFF

    long end = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime();

    Driver.timeResults[0][row][col] = end - start;
    Driver.results[row][col] = difference;
}

【问题讨论】:

    标签: java multithreading timing cpu-time


    【解决方案1】:

    您要么想要每个线程经过的时间,要么想要来自System.currentTime() 的“真实”经过时间;您的代码获取每个线程的时间,这并不总是与实际经过的时间相同。如果这是您想要的,那么您的实现应该可以工作。

    验证计时行为的一种简单方法是在已知持续时间内运行任务。 Thread.sleep(),例如。尝试将Thread.sleep() 与忙等待(即while(System.currentTimeMillis() &lt; timeInTheFuture) {})进行比较,您会注意到 CPU 时间可能会有所不同。不要期望高精度,但您仍然可以使用它来验证您的假设。如果您启动五个线程,每个线程工作 30 秒,您是否会为每个线程返回大约 30 秒?然后它正在做你期望的事情。

    也就是说,您似乎将计时信息存储在一个数组中,这不是一个好主意。 Arrays are not thread-safe。对于您的情况,最简单的方法可能是创建一个ConcurrentHashMap&lt;String, Long&gt;,其中键是线程名称,例如

    timeResults.put(Thread.currentThread().getName(), end - start);
    

    【讨论】:

    • Thread.sleep() 的想法很好。至于数组,我是这么想的,但是如果在我读取数组之前保证所有线程都完成,真的有问题吗?例如,如果我使用 Thread.join()?
    • @Stephen 由于数组是在线程启动之前创建的,因此每个线程只写入一个单一的位置,并且大概只有在所有线程加入后才读取数组(否则是明显的问题)声称是错误的。没有竞争条件,程序完全有效。线程创建和线程加入都发生在与相关线程中的先前代码的关系之前,因此没有两个线程写入相同的位置,并且没有在没有同步的情况下交错的读取和写入。
    • 倾向于使用显式线程安全类进行所有线程间通信。此外,无论如何,对于这个用例来说,映射更清晰 - 您正在将线程映射到值。
    • @dimo414 如果不理解手头的问题,使用线程安全类只会掩盖更严重的问题。您可能更喜欢这里的字典(然后您确实需要一个并发的 - 为什么?)但不要争辩说在这种情况下使用数组不安全,因为这是错误的。
    • 我同意在这种情况下,数组可以工作,但是您的用例很容易更改,因此它不会。使用线程安全的数据结构很容易发现并且对未来的变化具有鲁棒性。跨线程共享数组是一种反模式,即使 在这种特定情况下不是问题。
    【解决方案2】:

    如果您想测量 CPU 在每个线程中花费的时间,那么可以,您的代码看起来是正确的。请注意,虽然它不会测量从线程开始到完成的实际时间 - 为此您将使用 System.nanoTime()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-02
      • 1970-01-01
      • 1970-01-01
      • 2019-04-07
      • 1970-01-01
      • 1970-01-01
      • 2012-02-23
      • 1970-01-01
      相关资源
      最近更新 更多