Thread模拟处理器完成并行的quick sort。一开始不会同步线程,while总是结束不了,总有线程不能结束。发现了java自带很好用的barrier类CyclicBarrier
,但是有的processor结束任务后线程总数减少了,而barrier设定count之后不太方便修改,修改了就浪费了barrier循环的意义。所以还是选择用了一次性的CountDownLatch
。两者其实差不多。
直接贴代码:
import java.util.concurrent.CountDownLatch;
public class ArrayWithParallelQuickSort {
int n;
int[] a, b;
private static int[] f = new int[3005];
private static int[] lc = new int[3005];
private static int[] rc = new int[3005];
private int root, alive, tmp;
//private CyclicBarrier barrier;
private CountDownLatch step1, step2, step3, step4, step5;
ArrayWithParallelQuickSort(int x[]) {
this.b = x.clone();
this.n = b.length;
}
private class myprocessor extends Thread {
int i;
myprocessor (int i) {
this.i = i;
}
@Override
public void run() {
try {
root = i;
step1.countDown();step1.await();
f[i] = root;
lc[i] = rc[i] = n+1;
step2.countDown();step2.await();
if (i == root) return;
boolean flag = true;
while (flag) {
if (b[i] < b[f[i]] || b[i] == b[f[i]] && i < f[i]) {
lc[f[i]] = i;
step3.countDown();step3.await();
if (lc[f[i]] == i) {
alive--; flag = false;
}
else {
f[i] = lc[f[i]];
}
step4.countDown();step4.await();
}
else {
rc[f[i]] = i;
step3.countDown();step3.await();
if (rc[f[i]] == i) {
alive--; flag = false;
}
else {
f[i] = rc[f[i]];
}
step4.countDown();step4.await();
}
step5.countDown();step5.await();
}
}catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
public void sort() {
alive = n-1;
try {
step1 = new CountDownLatch(n);
step2 = new CountDownLatch(n);
step3 = new CountDownLatch(n);
step4 = new CountDownLatch(n);
for (int i = 0; i < n; i++) {
new myprocessor(i).start();
}
System.out.println("processor started.");
while (alive > 0) {
step5 = new CountDownLatch(alive + 1);
step3.countDown();step3.await();
//System.out.print("3");
step4.countDown();step4.await(); // alive的值只在step4可能被改变
//System.out.print("4");
step3 = new CountDownLatch(alive + 1);
step4 = new CountDownLatch(alive + 1);
step5.countDown();step5.await(); // 用于确保进入下一次循环前更新完同步变量
//System.out.print("5");
}
}catch (InterruptedException e1) {
e1.printStackTrace();
}
a = new int[3005];
tmp = 0;
dfs(root);
}
private void dfs(int i) {
if (i == n+1) return;
dfs(lc[i]);
a[tmp++] = b[i];
dfs(rc[i]);
}
}