我正在尝试在Java上编写一个multhithreaded版本的shell排序
这是单线程版本的代码
import java.util.*;
import java.util.Scanner.*;
class Test
{
public static void main (String [] args)
{
double [] list = new double [10000];
for (int i = 0; i < 10000; i++)
list[i] = 10000 - i;
long startTime = System.currentTimeMillis();
shellSort(list);
int elapsedTime = (int) (System.currentTimeMillis() - startTime);
System.out.println ("Time = " + elapsedTime);
for (double i : list)
System.out.print (i + " ");
}
public static void shellSort(double [] list)
{
int i, increment;
int [] k = {1, 4, 13, 40, 121, 364, 1093, 3280, 9841, 29524, 88573, 265720, 797161, 2391484};
for (i = k.length - 1; k[i] > list.length; i--);
for (i--; i >= 0; i--)
{
increment = k[i];
int upper = 2 * increment;
for (int count = increment; count < upper; count++)
insertionSort(list, increment, count);
}
}
public static void insertionSort(double [] list, int increment, int position)
{
for (int top = position; top < list.length;)
{
double item = list[top];
int i = top;
while (i - increment >= 0 && item < list[i - increment])
{
list[i] = list[i - increment];
i -= increment;
}
list[i] = item;
top += increment;
}
}
}
这是多线程版本的代码
import java.util.*;
import java.util.Scanner.*;
class MT extends Thread
{
double[] list;
int increment, position;
MT (double [] a, int b, int c)
{
list = a;
increment = b;
position = c;
}
public void run()
{
for (int top = position; top < list.length;)
{
double item = list[top];
int i = top;
while (i - increment >= 0 && item < list[i - increment])
{
list[i] = list[i - increment];
i -= increment;
}
list[i] = item;
top += increment;
}
}
}
class Test
{
public static void main (String [] args)
{
double [] list = new double [10000];
for (int i = 0; i < 10000; i++)
list[i] = 10000 - i;
long startTime = System.currentTimeMillis();
shellSort(list);
int elapsedTime = (int) (System.currentTimeMillis() - startTime);
System.out.println ("Time = " + elapsedTime);
for (double i : list)
System.out.print (i + " ");
}
public static void shellSort(double [] list)
{
int i, increment;
int [] k = {1, 4, 13, 40, 121, 364, 1093, 3280, 9841, 29524, 88573, 265720, 797161, 2391484};
for (i = k.length - 1; k[i] > list.length; i--);
for (i--; i >= 0; i--)
{
increment = k[i];
int upper = 2 * increment;
for (int count = increment; count < upper; count+=2)
{
new MT(list, increment, count).start();
new MT(list, increment, count + 1).start();
}
}
}
}
多线程版本比单线程版本需要更长的时间。两者都提供正确的输出,多线程版本使用我的3个内核而不是预期的2个。我的多线程程序导致这种减速的原因是什么?我唯一能想到的是,每当我调用MT类时,我都在创建包含数字的数组?
感谢。
答案 0 :(得分:1)
这是我用于创建多线程处理循环的模式。我已经使用了几十次,非常成功。模式总是一样的:shel
public class Test {
// the Task encapsulates the work to be done
public static class TestTask extends FutureTask<Doulbe[]> {
public TestTask(TestWorker worker) {
super(worker);
}
}
// the worker does the work, extends Callable
public static class TestWorker extends Callable<Double[]> {
public Double[] unsortedList;
public Double[] call() throws Exception {
// do the work, return the array of Doubles...
Double[] results = shellSort(unsortedList);
// do other stuff
return results;
}
}
public static void main (String [] args) {
BlockingQueue<Runnable> queue = new LinkedBlockingDeque<Runnable>();
// use a constant sized thread pool of 15 threads
ThreadPoolExecutor tpe = new ThreadPoolExecutor(15, 15, 1000L, TimeUnit.SECONDS, queue);
CopyOnWriteArrayList<TestTask> allTasks = new CopyOnWriteArrayList<TestTask>();
for (int i = 0; i < 10000; i++ ) {
TestWorker worker = new TestWorker();
worker.unsortedList = // your list to be sorted...
TestTask task = new TestTask(worker);
allTasks.add(task);
tpe.execute(task);
}
do {
// basically just loop until all tasks are finished.
// might be good to throw in a Thread.sleep(10000) here too
for ( TestTask task : allTasks ) {
if ( task.isDone() ) {
// if the task is done, remove it from the arraylist
// remember to remove the task before getting the results
allTasks.remove(task);
try {
Double[] sortedList = task.get();
// do something with the output.
} catch ( Exception e ) {
LOGGER.error("Task threw exception...", e);
}
}
}
} while ( allTasks.size() > 0);
}
}
答案 1 :(得分:0)
创建新Thread
会产生相当大的开销。看起来您可能在包含
for
语句中创建了一堆线程
new MT(list, increment, count).start();
考虑使用thread pool来减少初始化开销。