【发布时间】:2016-03-11 12:55:44
【问题描述】:
我有一个简单的 Java 多线程应用程序,如下所示:
class MyThreads extends Thread{
public void run() {
{
// some thread initializations
// every thread reads 2 files (its own files,
// so node 0 will read A0.txt and B0.txt
// and node 1 will read A1.txt and B1.txt)
// he files have sizes between 10-20MB.
// A's files contain different information for different nodes (A0.txt != A1.txt),
// but B's files are the same(B0.txt has
// the same info as B1.txt). This is just a scenario.
// it stores the data that was
// read before in the memory.
// Again, i know B can be shared since
// it has the same info in both threads, but it's not.
}
{
// simple computation on the data retrieved
// (addition, multiplication, etc)
// I assume there is no need to synchronize
// the threads since they apply operations on their own data.
// Here, every thread executes the same number of operations
}
{
// writing the results on different files. This phase in unimportant.
}
}
public static void main(String args[]) {
// start 4 threads
}
}
在测试初始化部分、计算部分的性能时,我得到了这些奇怪的结果:
2016-03-11-NodeThread:1 time[2318] tag[initialization]
2016-03-11-NodeThread:0 time[2379] tag[initialization]
2016-03-11-NodeThread:2 time[2474] tag[initialization]
2016-03-11-NodeThread:3 time[2481] tag[initialization]
2016-03-11-NodeThread:2 time[30ms] tag[computation]
2016-03-11-NodeThread:1 time[6ms] tag[computation]
2016-03-11-NodeThread:3 time[7ms] tag[computation]
2016-03-11-NodeThread:0 time[6ms] tag[computation]
正如我们所见,NodeThread:2 的计算耗时 30 毫秒,而其他节点的计算耗时不到 10 毫秒。
不过,在初始化和计算之间插入障碍后,我得到了很好的结果:
2016-03-11-NodeThread:1 time[2318] tag[initialization]
2016-03-11-NodeThread:0 time[2379] tag[initialization]
2016-03-11-NodeThread:2 time[2474] tag[initialization]
2016-03-11-NodeThread:3 time[2481] tag[initialization]
2016-03-11-NodeThread:2 time[30ms] tag[computation]
2016-03-11-NodeThread:1 time[33ms] tag[computation]
2016-03-11-NodeThread:3 time[29ms] tag[computation]
2016-03-11-NodeThread:0 time[31ms] tag[computation]
我的问题是:如果线程根本不通信,它们从磁盘的不同部分读取,并且它们执行相同数量的计算,为什么需要在计算之前同步它们?我的猜测是涉及到缓存,但我无法解释原因。
注意。我测试代码的机器有超过 4 个内核,没有其他消耗 CPU 的进程正在运行。为了测量我这样使用 perf4j 的时间。
class MyThreads extends Thread{
public void run() {
{
StopWatch stopWatch = new Log4JStopWatch();
// some thread initializations
// every thread reads 2 files (its own files,
// so node 0 will read A0.txt and B0.txt
// and node 1 will read A1.txt and B1.txt)
// he files have sizes between 10-20MB.
// A's files contain different information for different nodes (A0.txt != A1.txt),
// but B's files are the same(B0.txt has
// the same info as B1.txt). This is just a scenario.
// it stores the data that was
// read before in the memory.
// Again, i know B can be shared since
// it has the same info in both threads, but it's not.
stopWatch.stop("initialization");
// barrier
}
{
StopWatch stopWatch = new Log4JStopWatch();
// simple computation on the data retrieved
// (addition, multiplication, etc)
// I assume there is no need to synchronize
// the threads since they apply operations on their own data.
// Here, every thread executes the same number of operations
stopWatch.stop("computation");
}
{
// writing the results on different files. This phase in unimportant.
}
}
public static void main(String args[]) {
// start 4 threads
}
}
【问题讨论】:
-
您认为为什么需要同步?您所展示的只是同步会使事情变慢,这本身并不令人惊讶。
-
您是否使用 ExecutorService 运行线程?文件大小可能会影响线程执行时间。根据我的观察,线程数应等于内核数(或由于上下文切换而为 + 1)。您是否同步公共监视器对象上的线程?请发布更多代码而不是 cmets。
-
您的问题是哪一个?标题中的那个还是正文中的那个?他们几乎没有任何共同点。
-
标题中的那个,对不起。
-
要使用的线程数本身就是一门科学。首先是不同版本的 Java 可能会为相同的硬件提供不同的“内核数”。
标签: java multithreading performance-testing