Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 什么才是真正的“;预热&x201D;多线程处理上的线程?_Java_Multithreading_Warm Up - Fatal编程技术网

Java 什么才是真正的“;预热&x201D;多线程处理上的线程?

Java 什么才是真正的“;预热&x201D;多线程处理上的线程?,java,multithreading,warm-up,Java,Multithreading,Warm Up,我正在处理Java中的多线程,正如有人向我指出的那样,我注意到线程正在升温,也就是说,它们在重复执行时会变得更快。我想了解为什么会发生这种情况,以及它是否与Java本身有关,或者它是否是每个多线程程序的常见行为 彼得·劳瑞(Peter Lawrey)的代码举例如下: for (int i = 0; i < 20; i++) { ExecutorService es = Executors.newFixedThreadPool(1); final double[] d = n

我正在处理Java中的多线程,正如有人向我指出的那样,我注意到线程正在升温,也就是说,它们在重复执行时会变得更快。我想了解为什么会发生这种情况,以及它是否与Java本身有关,或者它是否是每个多线程程序的常见行为

彼得·劳瑞(Peter Lawrey)的代码举例如下:

for (int i = 0; i < 20; i++) {
    ExecutorService es = Executors.newFixedThreadPool(1);
    final double[] d = new double[4 * 1024];
    Arrays.fill(d, 1);
    final double[] d2 = new double[4 * 1024];
    es.submit(new Runnable() {
    @Override
    public void run() {
        // nothing.
    }
    }).get();
    long start = System.nanoTime();
    es.submit(new Runnable() {
    @Override
    public void run() {
        synchronized (d) {
            System.arraycopy(d, 0, d2, 0, d.length);
        }
    }
    });
    es.shutdown();
    es.awaitTermination(10, TimeUnit.SECONDS);
    // get a the values in d2.
    for (double x : d2) ;
    long time = System.nanoTime() - start;
    System.out.printf("Time to pass %,d doubles to another thread and back was %,d ns.%n", d.length, time);
}
也就是说,它变得更快,稳定在50纳秒左右。为什么呢

如果我运行这段代码(20次重复),然后执行其他操作(比如说对之前的结果进行后处理并为下一轮多线程阅读做准备),然后在相同的
ThreadPool
上执行相同的
Runnable
再重复20次,那么无论如何,它都已经预热了


在我的程序中,我只在一个线程中执行
Runnable
(实际上,我拥有的每个处理核心都有一个线程,这是一个CPU密集型程序),然后交替多次执行其他一些串行处理。它似乎并没有随着程序的进行而变得更快。也许我可以找到一种方法来预热它…

不是线程,而是JVM

JVM具有所谓的JIT(实时)编译。当程序运行时,它会分析程序中发生的事情,并动态优化程序。它通过获取JVM运行的字节码并将其转换为运行速度更快的本机代码来实现这一点。它可以以一种适合您当前情况的方式来实现这一点,因为它通过分析实际的运行时行为来实现这一点。这可能(并非总是)导致极大的优化。甚至比一些编译成本机代码而不具备这些知识的程序更重要

你可以在网上多读一点


当代码加载到CPU缓存中时,您可能会在任何程序上获得类似的效果,但我相信这将是一个较小的差异。

我认为线程执行速度最终会更快的唯一原因是:

  • 内存管理器可以重用已分配的对象空间(例如,让堆分配填满可用内存,直到达到最大内存-
    Xmx
    属性)

  • 工作集在硬件缓存中可用

  • 重复操作可能会创建编译器可以更轻松地重新排序以优化执行的操作


这些原因与Java或其他语言无关?是和否。许多编程语言确实重用对象空间进行重新分配,而
JIT
(即时编译)优化主要针对JVM/.NET语言。不过,硬件缓存在所有平台上都很常见。感谢您的解释,@rfeak。但是你认为编译器能优化我的程序吗?(请阅读我添加到问题的最后一段)JIT编译器只能做这么多,而且只影响CPU时间。如果您的串行进程涉及任何类型的IO,编译器几乎无法完成。我建议你分析一下你的程序,看看时间花在哪里,如果你需要更高的性能,然后攻击最大的瓶颈。实际上,它没有任何IO。我给出了初始条件,程序自行运行。我解了一些特殊类型的微分方程。@usoouindio-如果这只是CPU限制,JIT编译器应该会有一些好处。然而,我坚持我的建议。如果您需要更高的速度,请使用探查器查找瓶颈并对其进行攻击。