在Java中并行化快速排序时,线程永远不会返回join()。为什么?
我用Java编写了并行化快速排序算法的简单代码,在运行方法中,我每次都创建两个独立的新线程,用于并行处理数组元素。但是,当它遇到两个创建的线程的join()语句时,线程从未返回并停止join(),似乎join()从未释放它们 下面是代码在Java中并行化快速排序时,线程永远不会返回join()。为什么?,java,multithreading,parallel-processing,quicksort,Java,Multithreading,Parallel Processing,Quicksort,我用Java编写了并行化快速排序算法的简单代码,在运行方法中,我每次都创建两个独立的新线程,用于并行处理数组元素。但是,当它遇到两个创建的线程的join()语句时,线程从未返回并停止join(),似乎join()从未释放它们 下面是代码 class StartJoinQuickSort implements Runnable { private int m_Low, m_High; private int[] m_Array = null; private final
class StartJoinQuickSort implements Runnable
{
private int m_Low, m_High;
private int[] m_Array = null;
private final static int NR_OF_VALUES = 10; // TOTAL_NO_VALUES
private int PivotElement;
private static Random m_random = new Random( );
public StartJoinQuickSort(int[] a_Array,int a_Low,int a_High)
{
this.m_Array = a_Array;
this.m_Low = a_Low;
this.m_High = a_High;
}
private void SwapArrayElements(int a_i,int a_j)
{
int temp = this.m_Array[a_i];
this.m_Array[a_i] = this.m_Array[a_j];
this.m_Array[a_j] = temp;
}// end of SwapArrayElements
private static int nextRandomFunctionValue(int aStart, int aEnd)
{
if ( aStart > aEnd )
{
throw new IllegalArgumentException("Start cannot exceed End.");
}
//get the range, casting to long to avoid overflow problems
long range = (long)aEnd - (long)aStart + 1;
// compute a fraction of the range, 0 <= frac < range
long fraction = (long)(range * m_random.nextDouble());
int randomNumber = (int)(fraction + aStart);
return randomNumber;
}// end of nextRandomFunctionValue
private static int[] GetArrayWithRandomValues()
{
int[] ArrayToBePopulatedWithRandomValues = new int[NR_OF_VALUES];
for(int index =0; index<NR_OF_VALUES;index++)
{
int RandomValue = StartJoinQuickSort.nextRandomFunctionValue(0,NR_OF_VALUES);
ArrayToBePopulatedWithRandomValues[index] = RandomValue;
}//end of for
return ArrayToBePopulatedWithRandomValues;
}//end of GetArrayWithRandomValues
private int middleIndex(int left, int right)
{
return left + (right - left) / 2;
}
public int Partition(int a_Start,int a_end)
{
// System.out.println("Partition ..thId : " + Thread.currentThread().getId());
int pivotIndex = 0;
int i = a_Start;
int j = a_end;
try
{
pivotIndex = middleIndex(a_Start , a_end);
this.PivotElement = this.m_Array[pivotIndex];
do
{
while(this.m_Array[i] < PivotElement )
i++;
if(j>0)
{
try
{
while( this.m_Array[j] > PivotElement )
j--;
}
catch(Exception ex){System.out.println(" j : " + j);}
}//end of if
if(i<=j)
{
SwapArrayElements(i,j);
// System.out.println("Swap .." + + Thread.currentThread().getId());
i++;
j--;
}//end of if
}while(i<=j);
}
catch(Exception except)
{
System.out.println("exception in Partition " + except);
}
return j;
}
public void run()
{
//System.out.println("in run..");
//System.out.println("after PARTITION");
StartJoinQuickSort oStartQuickSort_1 = null;
StartJoinQuickSort oStartQuickSort_2 = null;
if(this.m_Low < this.m_High )
{
int Index = Partition(this.m_Low,this.m_High);
Thread thPart_1 = new Thread ( new StartJoinQuickSort( this.m_Array,this.m_Low,Index ) );
Thread thPart_2 = new Thread ( new StartJoinQuickSort( this.m_Array,Index + 1,this.m_High ) );
thPart_1.start(); thPart_2.start();
//}//end of if
//if( Index + 1 < this.m_High)
//{
try
{
thPart_1.join(); thPart_2.join();
}catch (InterruptedException e) { e.printStackTrace();}
}
}//end of run
类StartJoinQuickSort实现可运行
{
私人国际货币单位低,货币单位高;
私有int[]m_数组=null;
private final static int NR_OF_VALUES=10;//总计没有值
私有int数据透视元素;
私有静态随机m_Random=new Random();
公共StartJoinQuickSort(int[]数组,int a_低,int a_高)
{
this.m_数组=a_数组;
这个m_Low=a_Low;
这个m_高=a_高;
}
私人空间交换要素(int a_i,int a_j)
{
int temp=这个.m_数组[a_i];
this.m_数组[a_i]=this.m_数组[a_j];
这个.m_数组[a_j]=temp;
}//Swaparlayements结束
私有静态int nextRandomFunctionValue(int aStart、int aEnd)
{
如果(aStart>aEnd)
{
抛出新的IllegalArgumentException(“开始不能超过结束”);
}
//获得射程,长距离施放以避免溢出问题
长距离=(长)方向-(长)方向+1;
//计算范围的一小部分(0个元素)
j--;
}
catch(异常ex){System.out.println(“j:+j);}
}//if结束
如果(ijoin()如果你的线程没有完成,就会阻塞。你需要确定为什么你的线程没有完成。你能试着用调试器调试你的程序吗?如果你有低=0,高=1,会发生什么?如果你的分区返回1,你将有一个无限的线程循环,对吗?Hmmm,实现递归算法从来都不是一个好主意与此并行,您最终将创建大量线程(每个级别都是指数级的),并最终超额订阅系统
最好的办法是设置一个截止点,比如说,它等于可用内核的数量。然后,当当前递归级别的分支数量等于截止点时,切换到顺序快速排序。流的一些非常粗糙的伪代码:
parallel_quicksort(level, interval) {
// compute subintervals interval1, interval2
if(level < cutoff) {
spawn1: parallel_quicksort(level + 1, interval1);
spawn2: parallel_quicksort(level + 1, interval2);
join1();
join2();
} else {
quicksort(interval1);
quicksort(interval2);
}
}
并行快速排序(级别、间隔){
//计算子区间间隔1,间隔2
如果(电平<截止值){
第1级:并行快速排序(级别+1,间隔1);
第2级:并行快速排序(级别+1,间隔2);
join1();
join2();
}否则{
快速排序(间隔1);
快速排序(间隔2);
}
}
还可以查看此实现,看看您是否遗漏了什么:谢谢大家的建议和建议。 我自己发现了这个问题,是配分函数的问题,它有一些问题,我选择了另一个,它对我来说很好 新的分区程序是: 公共int分区(int[]a_数组,int a_左,int a_右) { //为轴心选择范围的中间值 int pivotValue=a_数组[middleIndex(a_左,a_右)]
——左一;
++是的;
while(true)
{
做
++a_左;
while(a_数组[a_Left]pivotValue);
if(左a_<右a_)
Swaparlayements(左a_,右a_);
其他的
{
返回一个_的权利;
}
}
}
BTW,这是一种非常幼稚的并行快速排序方法。创建所有线程所花费的时间将超过并行化所获得的时间。有关使用JDK7的新ForkJoinPool的解决方案,请参阅。我已经完成了ForkJoin,但我希望这部分完成(幼稚的方式)。恐怕您需要向我们展示StartJoinQuickSort
的源代码,以便我们能够告诉我们为什么它永远不会结束。还有分区
的代码。我在上面添加了整个快速排序代码。我只有大约50个值或100个值要排序,为什么它不结束,这是我面临的问题。它只是需要对50个值或100个值进行排序。我进行了调试,它只是在处理中始终在分区内处理不同的线程。似乎它创建了无数不同的线程,并以处理分区的方式进行处理。可能是什么问题..您应该能够在调试器中看到这一点。您应该能够确定它应该何时停止创建线程。W在这一点上会发生什么,应该发生什么?我会尝试一个较小的集合,如3或5个值,因为它可能更容易调试。然后与10个值这样的小人物共享结果。我正在调试一些方法,并进行一些干运行…多谢Tudor的建议。你能给我看一下级别吗…?如何计算级别并将其传递给quicksort过程。截止点是pivot索引…对吗?我的意思是在快速排序中,解决方法是找到一些pivot元素,然后对过程进行一些递归(这里通常为每次调用快速排序过程创建线程),那么你所说的中断是什么意思?和级别..?你能给我看一些java代码或更好的理解吗。@乌斯曼:当你开始计算时,级别将从0开始。中断将被计算为产生线程数等于核心数的级别。例如,如果你有4个核心,那么中断将是1,因为e在级别0,您生成2个线程,然后在级别1,每个线程生成另外2个线程,因此总共有4个线程。您可以使用Runtime.getRuntime().availableProcessors()获得内核的数量;默认情况下,JDK7 ForkJoinPool通常会使用与处理器数量相同的线程。然后,它会在代码中的Fork和Join之后将任务排队。
--a_Left;
++a_Right;
while (true)
{
do
++a_Left;
while (a_Array[a_Left] < pivotValue);
do
--a_Right;
while (a_Array[a_Right] > pivotValue);
if (a_Left < a_Right)
SwapArrayElements(a_Left,a_Right);
else
{
return a_Right;
}
}
}