数据量非常大的时候用多线程排序应该会很快的吧,虽然网上有不少多线程排序的例子,但是感觉都很复杂的样子,所以今天我们用最基础的知识写一个最简单的,用的是java语言。
如果使用多线程的话,快速排序应该是最合适的,因为快排是分区进行的(Arrays.sort()中可以找到快速排序的代码)。
我们先利用快排算法把数组分成两部分:
关于快速排序可以参考这个(需要稍作修改以应对数组中有重复元素的情况)
http://www.cnblogs.com/luchen927/archive/2012/02/29/2368070.html
int[] arr = { 5, 3, 7, 4, 8, 9, 55, 44, 33, 22, 11, 11, 4, 5, 6, 7, 3,
2, 66, 44, 2, 34, 21, 6, 54 };
int key = arr[0]; // 以第一个数为关键数
int low = 0;
int high = arr.length - 1;
while (low < high) {
while (low < high && arr[high] >= key) {
high--;
}
arr[low] = arr[high]; // 从后向前遍历,找到小于关键数的元素放到前面
while (low < high && arr[low] <= key) {
low++;
}
arr[high] = arr[low]; // 从前向后遍历,找到大于关键数的元素放到后边
}
arr[low] = key; // 完成本次交换,把关键数插入中间位置,把数组分为两段
这样我们就得到了arr[0]-arr[low-1]和arr[low+1]-arr[arr.length-1]这两个数组区间,接下来我们构造线程分别对他们进行排序(不需要同步),并在每一次分区后输出数组以便使过程更加直观:
class SortThread extends Thread {
private int left, right;
private int[] arr;
SortThread(int[] arr, int left, int right) {
this.arr = arr;
this.left = left;
this.right = right;
} // run()不带参数,所以用构造方法传入参数
private void sort(int[] arr, int left, int right) {
if (left < right) {
int key = arr[left];
int low = left;
int high = right;
while (low < high) {
while (low < high && arr[high] >= key) {
high--;
}
arr[low] = arr[high];
while (low < high && arr[low] <= key) {
low++;
}
arr[high] = arr[low];
}
arr[low] = key;
System.out.println(Arrays.toString(arr));
sort(arr, left, low - 1);
sort(arr, low + 1, right);
}
} //这一部分跟上面的一样
@Override
public void run() {
sort(arr, left, right); // 调用排序算法
}
}
现在只要开启两个线程就行了:
SortThread p1 = new SortThread(arr, 0, low - 1); // 对前一段排序
SortThread p2 = new SortThread(arr, low + 1, arr.length - 1); // 对后一段排序
p1.start();
p2.start();
输出结果如下:
[2, 3, 2, 4, 3, 4, 5, 44, 33, 22, 11, 11, 55, 5, 6, 7, 9, 8, 66, 44, 7, 34, 21, 6, 54]
[2, 3, 2, 4, 3, 4, 5, 44, 33, 22, 11, 11, 55, 5, 6, 7, 9, 8, 66, 44, 7, 34, 21, 6, 54]
[2, 2, 3, 4, 3, 4, 5, 44, 33, 22, 11, 11, 55, 5, 6, 7, 9, 8, 66, 44, 7, 34, 21, 6, 54]
[2, 2, 3, 3, 4, 4, 5, 44, 33, 22, 11, 11, 55, 5, 6, 7, 9, 8, 66, 44, 7, 34, 21, 6, 54]
[2, 2, 3, 3, 4, 4, 5, 6, 33, 22, 11, 11, 21, 5, 6, 7, 9, 8, 34, 44, 7, 44, 66, 55, 54]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 22, 11, 11, 21, 33, 6, 7, 9, 8, 34, 44, 7, 44, 66, 55, 54]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 11, 11, 21, 8, 6, 7, 9, 22, 34, 44, 33, 44, 66, 55, 54]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 11, 21, 8, 11, 7, 9, 22, 34, 44, 33, 44, 66, 55, 54]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 9, 7, 8, 11, 11, 21, 22, 34, 44, 33, 44, 66, 55, 54]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 7, 9, 11, 11, 21, 22, 34, 44, 33, 44, 66, 55, 54]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 11, 11, 21, 22, 34, 44, 33, 44, 66, 55, 54]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 11, 11, 21, 22, 33, 34, 44, 44, 66, 55, 54]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 11, 11, 21, 22, 33, 34, 44, 44, 54, 55, 66]
[2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 11, 11, 21, 22, 33, 34, 44, 44, 54, 55, 66]
要注意的是,这种代码虽然可以用超大号的样本进行试验,但是一不小心就会溢出呀。