Java 为什么我的线程排序算法比非线程版本慢?

Java 为什么我的线程排序算法比非线程版本慢?,java,multithreading,Java,Multithreading,我刚刚实现了合并排序的线程版本ThreadedMerge.java: 因为合并排序是一种分治算法,所以我为数组的每一半创建一个线程。但是Java VM中可访问线程的数量有限,因此我在创建线程之前检查: if(num <= nrOfProcessors){ num += 2; //create more threads }else{ //continue without threading } 排序需要大约200 ms的时间。这是我的算法的更新,为什么这一行代码会让情况

我刚刚实现了合并排序的线程版本ThreadedMerge.java

因为合并排序是一种分治算法,所以我为数组的每一半创建一个线程。但是Java VM中可访问线程的数量有限,因此我在创建线程之前检查:

if(num <= nrOfProcessors){
    num += 2;
   //create more threads
}else{
   //continue without threading
}

排序需要大约200 ms的时间。这是我的算法的更新,为什么这一行代码会让情况变得更糟?

Hhm,你不应该为每一步创建一个线程(它们很昂贵,而且有轻量级的替代方案。)

理想情况下,如果有4个CPU,您应该只创建4个线程

假设您有4个CPU,然后在第一级创建一个线程(现在有2个),在第二级创建一个新线程。这给你4

之所以只创建一个线程而不创建两个线程,是因为您可以使用当前运行的线程,如下所示:

Thread t = new Thread(...);
t.start();

// Do half of the job here

t.join(); // Wait for the other half to complete.
如果你有,比方说,5个CPU(不是两个CPU的能力),那么就创建8个线程


在实践中实现这一点的一个简单方法是,在达到适当的级别时创建您已经创建的非线程版本。这样可以避免在if语句等出现时使合并方法变得混乱。

首先,对num的访问不是线程安全的(检查)

您为核心创建了等量的进程,但通过join调用阻止了一半进程

num += 1;
ThreadedMerge tm1 = new ThreadedMerge(array, startIndex, startIndex + halfLength);
tm1.start();
sortedRightPart = mergeSort(array, startIndex + halfLength, endIndex);
try{
    tm1.join(); 
    num-=1
    sortedLeftPart = tm1.list;
}catch(InterruptedException e){
}

这不会阻止调用线程,而是使用它对正确的部分进行排序,当一个线程返回它所占用的空间可供另一个线程使用时,让创建的线程执行另一部分。对
运行时的调用。availableProcessors()
似乎占用了相当多的额外时间。您只需要调用它一次,因此只需将其移出方法并将其定义为静态,例如:

static int nrOfProcessors = Runtime.getRuntime().availableProcessors();

我不知道您的数据,但对于小型阵列,创建线程的开销将很容易超过并行收益。另外,您知道线程是否真的位于不同的处理器中吗?请将代码分为两部分:)一部分进行实际排序,另一部分启动线程。那会容易得多。在我的笔记本电脑(双核)上,您的代码启动了4个线程,因此在处理线程时出现了一些问题。我只是将max number设置为4,与创建1000个线程相比,性能没有变化:D。为什么不让这1000个线程以同样的方式为每个线程分配整个计算工作?@ArtWorkAD No,因为你的代码有一些根本性的错误。我不知道你的意思,但是创建1000个线程是一个非常糟糕的主意——创建1000个OS线程需要很长时间。
static int nrOfProcessors = Runtime.getRuntime().availableProcessors();