多线程对象的创建要比单线程慢

编程入门 行业动态 更新时间:2024-10-13 06:13:04
本文介绍了多线程对象的创建要比单线程慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我有一个基本的问题.当我创建1亿个哈希表时,如果我在单个内核上执行,则大约需要6秒钟(运行时=每个内核6秒钟).如果我在12个内核(我的机器有6个允许超线程的内核)上执行多线程,则大约需要10秒钟(运行时间=每个内核112秒).

I have what probably is a basic question. When I create 100 million Hashtables it takes approximately 6 seconds (runtime = 6 seconds per core) on my machine if I do it on a single core. If I do this multi-threaded on 12 cores (my machine has 6 cores that allow hyperthreading) it takes around 10 seconds (runtime = 112 seconds per core).

这是我使用的代码:

主要

public class Tests { public static void main(String args[]) { double start = System.currentTimeMillis(); int nThreads = 12; double[] runTime = new double[nThreads]; TestsThread[] threads = new TestsThread[nThreads]; int totalJob = 100000000; int jobsize = totalJob/nThreads; for(int i = 0; i < threads.length; i++) { threads[i] = new TestsThread(jobsize,runTime, i); threads[i].start(); } waitThreads(threads); for(int i = 0; i < runTime.length; i++) { System.out.println("Runtime thread:" + i + " = " + (runTime[i]/1000000) + "ms"); } double end = System.currentTimeMillis(); System.out.println("Total runtime = " + (end-start) + " ms"); } private static void waitThreads(TestsThread[] threads) { for(int i = 0; i < threads.length; i++) { while(threads[i].finished == false)//keep waiting untill the thread is done { //System.out.println("waiting on thread:" + i); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } } } }

线程

import java.util.HashMap; import java.util.Map; public class TestsThread extends Thread { int jobSize = 0; double[] runTime; boolean finished; int threadNumber; TestsThread(int job, double[] runTime, int threadNumber) { this.finished = false; this.jobSize = job; this.runTime = runTime; this.threadNumber = threadNumber; } public void run() { double start = System.nanoTime(); for(int l = 0; l < jobSize ; l++) { double[] test = new double[65]; } double end = System.nanoTime(); double difference = end-start; runTime[threadNumber] += difference; this.finished = true; } }

我不明白为什么要在多个线程中同时创建对象,而每个线程要花更长的时间,而在一个线程中却要串行地创建对象,为什么花更长的时间.如果删除创建哈希表的行,此问题将消失.如果有人可以帮助我,我将非常感激.

I do not understand why creating the object simultaneously in multiple threads takes longer per thread then doing it in serial in only 1 thread. If I remove the line where I create the Hashtable this problem disappears. If anyone could help me with this I would be greatly thankful.

推荐答案

更新:此问题与错误报告,并已通过Java 1.7u40修复.而且Java 1.8从来都不是问题,因为Java 8具有完全不同的哈希表算法.

Update: This problem has an associated bug report and has been fixed with Java 1.7u40. And it was never an issue for Java 1.8 as Java 8 has an entirely different hash table algorithm.

由于您没有使用所创建的对象,因此可以优化操作.因此,您只需衡量创建线程的开销.当然,开销越大,启动的线程越多.

Since you are not using the created objects that operation will get optimized away. So you’re only measuring the overhead of creating threads. This is surely the more overhead the more threads you start.

我必须更正关于细节的答案,但我还不知道:Hashtable和HashMap类有些特殊之处.它们都在构造函数中调用sun.misc.Hashing.randomHashSeed(this).换句话说,它们的实例在构造期间逸出,这对内存可见性有影响.这意味着与ArrayList不同,它们的构造无法优化,并且由于该方法内部发生的事情(即同步),导致多线程构造的速度变慢.

I have to correct my answer regarding a detail, I didn’t know yet: there is something special with the classes Hashtable and HashMap. They both invoke sun.misc.Hashing.randomHashSeed(this) in the constructor. In other words, their instances escape during construction which has an impact on the memory visibility. This implies that their construction, unlike let’s say for an ArrayList, cannot optimized away, and multi-threaded construction slows down due to what happens inside that method (i.e. synchronization).

如前所述,这是这些类的特殊设置,当然还有这种实现(我的设置:1.7.0_13).对于普通的类,此类代码的构造时间直接变为零.

As said, that’s special to these classes and of course this implementation (my setup:1.7.0_13). For ordinary classes the construction time goes straight to zero for such code.

在这里,我添加了更复杂的基准代码.观察DO_HASH_MAP = true和DO_HASH_MAP = false之间的区别(当false它将创建一个ArrayList而不具有这种特殊行为).

Here I add a more sophisticated benchmark code. Watch the difference between DO_HASH_MAP = true and DO_HASH_MAP = false (when false it will create an ArrayList instead which has no such special behavior).

import java.util.*; import java.util.concurrent.*; public class AllocBench { static final int NUM_THREADS = 1; static final int NUM_OBJECTS = 100000000 / NUM_THREADS; static final boolean DO_HASH_MAP = true; public static void main(String[] args) throws InterruptedException, ExecutionException { ExecutorService threadPool = Executors.newFixedThreadPool(NUM_THREADS); Callable<Long> task=new Callable<Long>() { public Long call() { return doAllocation(NUM_OBJECTS); } }; long startTime=System.nanoTime(), cpuTime=0; for(Future<Long> f: threadPool.invokeAll(Collections.nCopies(NUM_THREADS, task))) { cpuTime+=f.get(); } long time=System.nanoTime()-startTime; System.out.println("Number of threads: "+NUM_THREADS); System.out.printf("entire allocation required %.03f s%n", time*1e-9); System.out.printf("time x numThreads %.03f s%n", time*1e-9*NUM_THREADS); System.out.printf("real accumulated cpu time %.03f s%n", cpuTime*1e-9); threadPool.shutdown(); } static long doAllocation(int numObjects) { long t0=System.nanoTime(); for(int i=0; i<numObjects; i++) if(DO_HASH_MAP) new HashMap<Object, Object>(); else new ArrayList<Object>(); return System.nanoTime()-t0; } }

更多推荐

多线程对象的创建要比单线程慢

本文发布于:2023-11-23 12:59:44,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1621533.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:要比   多线程   单线程   对象

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!