【问题标题】:Cause of delay in multi-threading多线程延迟的原因
【发布时间】:2019-04-14 17:01:58
【问题描述】:

我用 Java 编写了一个程序,在 for 循环中打印 100 万。

for (int i =0;i<1000000;i++){
     System.out.println(i);
}

花了大约7.5 seconds

我用Java写了一个自定义类,实现Runnable接口,它以2个参数为限制,打印2个值之间的值。

public class ThreadCustom implements  Runnable {

    int start;
    int end;
    String name;


    ThreadCustom(int start, int end, String name){
        this.start = start;
        this.end = end;
        this.name = name;

    }
    @Override
    public void run() {
       for(int i =start; i<=end;i++){
            System.out.println(i);
        }
    }
}

我创建了我的自定义线程类的 10 个对象,为每个对象分配了 100k 个数字块来打印,所以最后我得到了所有的 10 hundred thousands 打印(不一定按顺序),但它需要大约 9.5 秒。

2 seconds delay 的原因是什么?这是因为线程之间发生了时间切片和上下文切换吗?我正在执行一个 java 进程,它产生 10 个线程。我的想法是否正确?

更新:评论了System.out.println,看看它在迭代时的表现。

无线程打印时间

2019-04-14 22:18:07.111   // start
2019-04-14 22:18:07.116 // end

使用 ThreadCustom 类:

2019-04-14 22:26:42.339
2019-04-14 22:26:42.341

【问题讨论】:

  • 我的第一个猜测是一次锁定多个线程以尝试执行输出。但是,这并不是一个真正合适的基准。
  • System.out.println 是线程安全的,因此您的所有线程都在不断争用。
  • @JacobG。所以它会导致延迟,因为它允许一个线程一次使用它?
  • @DanyalSandeelo 我会说是的,因为在给定时间只能打印一个线程。我假设同步开销是导致延迟的原因。
  • 欢迎您随时乐于提供帮助,无论以何种方式提供帮助 ;-)

标签: java multithreading


【解决方案1】:

额外的时间以两种方式度过: 1) 设置每个线程执行上下文所涉及的开销 2) 您生成的线程数可能多于主处理器中可用的逻辑处理器数的可能情况

由于递增循环和打印整数所需的处理量很少,因此在大多数情况下,这会导致并行环境中的性能下降。

但是,如果您要在每次迭代期间对任何给定图像上不同的像素颜色进行计数,那么在使用多个线程时您会看到显着的性能优势。

【讨论】:

    【解决方案2】:

    我用 Java 编写了一个程序,在 for 循环中打印 [100 万]...我创建了 10 个自定义线程类的对象,...但是大约需要 9.5 秒。这 2 秒延迟的原因是什么?

    只有能够独立工作的线程才会更快。在将数字打印到System.out 的情况下,所有线程都试图争夺对same 资源System.out 的访问权,这是一个同步的PrintStream。这意味着大部分时间都浪费在等待另一个线程释放System.out 上的锁上。线程程序的任何额外“延迟”很可能是因为锁争用和线程之间的上下文切换。

    要适当地测试线程速度,您需要在每个线程中运行某种独立的 CPU 任务。多次计算Math.sqrt(...) 是一个更好的例子。在我较新的 Macbook 上,我可以在约 8.1 秒内执行 10 亿次(使用 b)Math.sqrt(...) 调用,但 10 个线程每个线程可以在约 1.1 秒内并行执行 1 亿次。但是等等,你可能会说,10 * 1.1 > 8 秒的总 CPU。我有 4 个内核,所以运行 10 个线程,有很多进出 CPU。 4 个线程每跑 250m 需要 2.1 秒,这与单线程示例的 8.1 秒非常接近。

    最后,Java 性能测试真的很难。我敢打赌,如果您多次运行这两个程序,您会看到一些不同的结果。任何快速运行的程序实际上都不能很好地判断速度,或者充其量只是一个非常粗略的近似值。此外,您需要小心,否则热插拔编译器可能会在运行时优化您的循环,因此您需要尝试做实际工作。

    【讨论】:

    • 感谢您的解释。我删除了 System.out.println 并且统计数据发生了变化。在我检查的所有运行中,线程一正在快速完成。所以基本上,线程在多处理器上分别执行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-01
    • 2017-10-05
    • 2016-11-07
    • 1970-01-01
    • 1970-01-01
    • 2021-04-19
    • 1970-01-01
    相关资源
    最近更新 更多