【发布时间】:2015-05-02 23:02:01
【问题描述】:
我一直试图在四核计算机上实现以下代码,并且执行器服务中的线程数超过 100 次迭代的平均运行时间如下
1 个线程 = 78404.95
2 个线程 = 174995.14
4 线程 = 144230.23
但根据我所研究的 2*(no of cores) 线程应该为程序提供最佳结果,这在我的程序中显然不是这种情况,它奇怪地为单线程提供了最佳时间。
代码:
import java.util.Collections;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class TestHashSet {
public static void main(String argv[]){
Set<Integer> S = Collections.newSetFromMap(new ConcurrentHashMap<Integer,Boolean>());
S.add(1);
S.add(2);
S.add(3);
S.add(4);
S.add(5);
long startTime = System.nanoTime();
ExecutorService executor = Executors.newFixedThreadPool(8);
int Nb = 0;
for(int i = 0;i<10;i++){
User runnable = new User(S);
executor.execute(runnable);
Nb = Thread.getAllStackTraces().keySet().size();
}
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long endTime = System.nanoTime();
System.out.println(0.001*(endTime-startTime)+" And "+Nb);
}
}
class User implements Runnable{
Set<Integer> S;
User(Set<Integer> S){
this.S = S;
}
@Override
public void run() {
// TODO Auto-generated method stub
Set<Integer> t =Collections.newSetFromMap(new ConcurrentHashMap<Integer,Boolean>());;
for(int i = 0;i<10;i++){
t.add(i+5);
}
S.retainAll(t);
Set<Integer> t2 =Collections.newSetFromMap(new ConcurrentHashMap<Integer,Boolean>());;
for(int i = 0;i<10;i++){
t2.add(i);
}
S.addAll(t);
/*
ConcurrentHashSet<Integer> D = new ConcurrentHashSet<Integer>();
for(int i=0;i<10;i++){
D.add(i+3);
}
S.difference(D);
*/
}
}
更新:如果我将每个线程的查询数增加到 1000,则 4 线程的性能优于单线程。当我每个线程仅使用大约 4 个查询并且没有查询时,我认为开销高于运行时现在增加的运行时间大于开销。谢谢
【问题讨论】:
-
线程也有很多开销。我听说过 2*NOfCores,但我已经获得了最佳性能,例如 NOfCores + 1。
-
@Carcigenicate 但是在大约 100 次迭代中,单线程的平均时间约为 1200 毫秒,5 线程的平均时间为 1700 毫秒。但是 5 线程应该提高性能..?
-
所以你根本没有增加 2 个线程?抱歉,我对您的时间有点困惑,因为上面有 1 个线程占用了 3569.707(我猜是毫秒)。
-
@Carcigenicate 当我在上面的代码中运行一个线程时,我得到一个线程大约 4000 和 2 个线程 4500 的时间,但是当我围绕整个代码运行 100 次并查看平均值时就像一个线程 - 1200 和 2 个线程 - 1400。
-
这很奇怪,抱歉。您绝对应该通过添加第二个线程来增加;我经常使用第二个线程获得几乎 2 倍的增长,但显然它取决于很多事情。我真的不知道,对不起。上次我遇到像你这样的情况时,事实证明这些任务实际上并没有被并行化。阅读文档以确保您不需要初始化某些内容以使其非顺序运行。
标签: java multithreading optimization concurrency