我正在研究一种排序算法,以显示名为BITONIC的多线程执行,但是我发现使用multhread来运行它的方式是创建新对象并在静态数组中工作,但是这导致了我难以置信的缓慢排序,通过一些调试-阅读打印品-我发现我正在创建大量的线程,因此创建了大量对象,我想是因为它是如此缓慢,但我无法真正解决问题,所以如果您能给我一些提示,我将非常感激。
Bitonic排序类似于合并,真正了解算法不是真正必要的,只需了解线程和Java
在这里,我具有一些具有单独线程的属性
public static int[] data;
private int start, end, size;
private boolean direction;
private int minimumLength = 1;
private final boolean Ascending = true, Descending = false;
我有2个构造函数,第一个实例,它们将从外部分配的向量中设置值
public MultiThreadedSorter (int[] originalData)
{
data = originalData;
start = 0;
end = size = data.length;
direction = Ascending;
// minimumLength = data.length / Runtime.getRuntime().availableProcessors();
minimumLength = 2;
}
另一种用于递归除法的方法,每个线程具有新值
private MultiThreadedSorter (int lo, int hi, boolean dir)
{
start = lo;
end = hi;
size = hi-lo;
direction = dir;
}
仅用于封装目的的排序
public void Sort()
throws InterruptedException
{
BitonicSort(start, end, direction);
}
此处是运行覆盖
@Override
public void run()
{
try
{
BitonicSort(start, end, direction);
} catch (InterruptedException ex)
{
Logger.getLogger(MultiThreadedSorter.class.getName()).log(Level.SEVERE, null, ex);
}
}
我认为问题出在这里
private void BitonicSort(int _lo, int _hi, boolean dir)
throws InterruptedException // join()
{
int length = _hi - _lo;
// System.out.println(Thread.currentThread().getName() + " - CRIADA");
// System.out.printf("%d\t%d\n", _lo, _hi);
if (length > 1)
{
// Show ("SORT", true);
if (length > minimumLength)
{
int mid = length / 2;
System.out.println("-- left - " + Thread.currentThread().getName());
MultiThreadedSorter leftSorterObj = new MultiThreadedSorter(_lo, _lo+mid, Ascending);
Thread left = new Thread(leftSorterObj);
left.start(); // i think that the problem is here
left.join(); // or here
System.out.println("-- rigth - " + Thread.currentThread().getName());
// System.out.printf("%d\t%d\n", _lo+mid, _hi);
MultiThreadedSorter rightSorterObj = new MultiThreadedSorter(_lo+mid, _hi, Descending);
Thread right = new Thread(rightSorterObj);
right.start(); // i think that the problem is here
right.join(); // or here
// System.out.println(Thread.currentThread().getName() + " - ENDED\n");
}
else
{
int mid = (length / 2);
if (mid > 1)
{
// Show ("R1", false);
BitonicSort(_lo, mid, Ascending);
// Show ("R2", false);
BitonicSort(_lo+mid, mid, Ascending);
}
}
BitonicMerge(_lo, _hi, dir);
}
}
现在,我将发布主类和完整类,仅当您要执行时
主要:
public class Program
{
public static void main(String[] args) throws InterruptedException
{
Random random = new Random();
int arraySize = (int) Math.pow(2, 7);
int[] originalData = new int[arraySize];
int lim = 20;
for (int i = 0; i < originalData.length; i++)
originalData[i] = random.nextInt(lim);
System.out.println(Arrays.toString(originalData));
System.out.printf("\n");
MultiThreadedSorter mult = new MultiThreadedSorter(originalData);
mult.Sort();
System.out.println(Arrays.toString(originalData));
System.out.println();
}
MultiThreadedSorter类别
public class MultiThreadedSorter //extends BaseBitonicSorter
implements Runnable
{
public static int[] data;
private int start, end, size;
private boolean direction;
private int minimumLength = 1;
private final boolean Ascending = true, Descending = false;
public MultiThreadedSorter (int[] originalData)
{
data = originalData;
start = 0;
end = size = data.length;
direction = Ascending;
// minimumLength = data.length / Runtime.getRuntime().availableProcessors();
minimumLength = 2;
}
// Construtor chamados por cada thread antes de iniciar
private MultiThreadedSorter (int lo, int hi, boolean dir)
{
start = lo;
end = hi;
size = hi-lo;
direction = dir;
}
public void Show (String msg, boolean r)
{
System.out.println(Thread.currentThread().getName() + "\t" + msg);
if (r)
System.out.printf("De: %d\tAte: %d\t Dir: %d\n", start, end, direction ? 1 : 0);
}
@Override
public void run()
{
try
{
BitonicSort(start, end, direction);
} catch (InterruptedException ex)
{
Logger.getLogger(MultiThreadedSorter.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void Sort()
throws InterruptedException
{
BitonicSort(start, end, direction);
}
private void BitonicSort(int _lo, int _hi, boolean dir)
throws InterruptedException // join()
{
int length = _hi - _lo;
// System.out.println(Thread.currentThread().getName() + " - CRIADA");
// System.out.printf("%d\t%d\n", _lo, _hi);
if (length > 1)
{
// Show ("SORT", true);
if (length > minimumLength)
{
int mid = length / 2;
System.out.println("-- left - " + Thread.currentThread().getName());
MultiThreadedSorter leftSorterObj = new MultiThreadedSorter(_lo, _lo+mid, Ascending);
Thread left = new Thread(leftSorterObj);
left.start();
left.join();
System.out.println("-- rigth - " + Thread.currentThread().getName());
// System.out.printf("%d\t%d\n", _lo+mid, _hi);
MultiThreadedSorter rightSorterObj = new MultiThreadedSorter(_lo+mid, _hi, Descending);
Thread right = new Thread(rightSorterObj);
right.start();
right.join();
// System.out.println(Thread.currentThread().getName() + " - ENDED\n");
}
else
{
int mid = (length / 2);
if (mid > 1)
{
// Show ("R1", false);
BitonicSort(_lo, mid, Ascending);
// Show ("R2", false);
BitonicSort(_lo+mid, mid, Ascending);
}
}
BitonicMerge(_lo, _hi, dir);
}
}
private void BitonicMerge(int _lo, int _hi, boolean dir)
throws InterruptedException // join()
{
// Show ("MERGE", true);
int length = _hi - _lo;
if (length > 1)
{
if (length > minimumLength)
{
int mid = (length / 2);
for (int i = _lo; i < (_lo + mid); i++)
Compare(i, (i + mid), dir);
MultiThreadedSorter leftMergerObj = new MultiThreadedSorter(_lo, _lo+mid, dir);
Thread left = new Thread(leftMergerObj);
left.start();
left.join();
MultiThreadedSorter rightMergerObj = new MultiThreadedSorter(_lo + mid, _hi, dir);
Thread right = new Thread(rightMergerObj);
right.start();
right.join();
}
else
{
int mid = (length / 2);
for (int i = _lo; i < (_lo + mid); i++)
Compare(i, (i + mid), dir);
if (mid > 1)
{
BitonicMerge(_lo, _lo + mid, dir);
BitonicMerge(_lo + mid, _hi, dir);
}
}
}
}
private synchronized void Compare(int src, int dst, boolean dir)
{
if (dir == (data[src] > data[dst]))
Exchange(src, dst);
}
protected synchronized void Exchange(int i, int j)
{
int temp = data[i];
data[i] = data[j];
data[j] = temp;
}
}
答案 0 :(得分:0)
为什么这么慢:
问题:您对进程可以创建的线程数不加任何限制,并且您正在递归地创建可能导致饱和的线程。
解决方案::使用线程池限制创建的线程数量(每个系统可以创建的线程数量有限)并减少线程的启动时间(每次使用new时) Thread(Runnable).start()用于创建新线程)。线程池可以通过Executors
接口进行管理。
问题:在并发方面,您的Compare和Exchange方法阻止所有线程的执行,因为它们被描述为synchronized
,因此只能由一个线程在以下位置运行一个时间。
解决方案::制作数据volatile