java - 尝试并行化快速排序以在Java中的多个线程上运行

标签 java parallel-processing quicksort

我有一个运行良好的快速排序算法,但是当我尝试并行化时,仅对数组的后半部分进行排序,另一半几乎没有变化。由于我是并行编程的新手,我不知道为什么。 我的解决方案是根据网上找到的不同代码组合而成的。 如何改进它以使整个数组排序?

public class foo {

  private static final int N_THREADS = Runtime.getRuntime().availableProcessors();
  private static final int FALLBACK = 2;
  private static Executor pool = Executors.newFixedThreadPool(N_THREADS);

  public static <T extends Comparable<T>> void sort(int[] numberArray){
    if(numberArray == null && numberArray.length == 0){
      return;
    }

    final AtomicInteger count = new AtomicInteger(1);
    pool.execute(new QuicksortRunnable<T>(numberArray, 0, numberArray.length-1, count));
  }

private static class QuicksortRunnable<T extends Comparable<T>> implements Runnable {

    private final int[] values;
    private final int left;
    private final int right;
    private final AtomicInteger count;

public QuicksortRunnable(int[] values, int left, int right, AtomicInteger count) {

      this.values = values;
      this.left = left;
      this.right = right;
      this.count = count;
    }

    @Override
    public void run() {
      quicksort(left, right);
      synchronized (count) {
        if (count.getAndDecrement() == 1)
          count.notify();
      }
    }

    private void quicksort(int pLeft, int pRight) {
      int pivotIndex = (pRight - pLeft) / 2 + pLeft;
      int pivot = values[pivotIndex];
      int j = pRight;
      int i = pLeft;

      while (i < j) {
        while (values[i] > pivot) {
          i++;
        }
        while (values[j] < pivot) {
          j--;
        }
        if (i <= j) {
          int temp = values[i];
          values[i] = values[j];
          values[j] = temp;
          i++;
          j--;
        }
      }
      if (count.get() >= FALLBACK * N_THREADS) {
        if (pLeft < j)
          quicksort(pLeft, j);
        if (i < pRight)
          quicksort(i, pRight);
      } else {


        if (pLeft < j) {
          count.getAndAdd(1);
          pool.execute(new QuicksortRunnable<T>(values, pLeft, j, count));
        }
        if (i < pRight) {
          count.getAndAdd(1);
          pool.execute(new QuicksortRunnable<T>(values, i, pRight, count));
        }
      }
    }
  }
~~~
My main function:
public static void main(String[] arg) {
    Random rand = new Random();
    int length = 1000;
    int[] toSort = new int[length];
    for(int i = 0; i<length; i++){
      toSort[i] = rand.nextInt(length);
    }

    sort(toSort);

    boolean sortedFH = true;
    boolean sortedSH = true;

    for(int i = 0; i<length/2; i++) {      
      if (toSort[i] < toSort[i + 1]) {
        sortedFH = false;
      }
    }
    for(int i = length/2; i<length-1; i++) {
      if (toSort[i] < toSort[i + 1]) {
        sortedSH = false;
      }
    }

    System.out.println();
    System.out.println("First half :" + sortedFH);
    System.out.println("Second half :" + sortedSH);
  }
}

Returns:
First half :false
Second half :true

编辑:删除了程序的一部分。我尝试了一些方法,但没有成功,发布问题时忘记将其删除。

最佳答案

首先,我认为您看到的结果主要是因为您在排序线程完成之前打印了结果。您需要等待所有线程完成才能检查结果。

根据您的代码,您可以使用 AtomicInteger 计数来阻止 sort() 返回,直到所有线程完成为止。

    public static <T extends Comparable<T>> void sort(int[] numberArray) {
        if (numberArray == null || numberArray.length == 0) {
            return;
        }

        final AtomicInteger count = new AtomicInteger(1);
        pool.execute(new QuicksortRunnable<T>(numberArray, 0, numberArray.length - 1, count));

        while (count.get() > 0) {
            synchronized (count) {
                count.wait();
            }
        }
    }
<小时/>

顺便说一句,除非是故意的,否则您的算法看起来会按降序对数组进行排序。我认为你需要翻转

        while (values[i] > pivot) {
          i++;
        }
        while (values[j] < pivot) {
          j--;
        }

        while (values[i] < pivot) {
          i++;
        }
        while (values[j] > pivot) {
          j--;
        }

这同样适用于主方法末尾的检查。

<小时/>

对 null 或空数组的检查应使用 OR 分隔,而不是 AND

        if (numberArray == null || numberArray.length == 0) {
           return;
        }

关于java - 尝试并行化快速排序以在Java中的多个线程上运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57590968/

相关文章:

clojure - 如何具体化 Prolog 的回溯状态以执行与 Clojure 中的 "lazy seq"相同的任务?

java - 启动JVM时-Xms和-Xmx参数是什么?

Java Hibernate 从某个索引或偏移量获取列表。

c++ - 哪个库用于迭代 1M*1k 次的并行 for 循环,OpenMP 或 boost::thread?

c - C 和 MPI 环境中的指针赋值

concurrency - GPar 的数据并行性

java - QuickSort(select)方法,ArrayIndex越界错误

java - 如何减少 JSF 中的 javax.faces.ViewState

java - 我应该使用什么 View 来存储音乐播放器的歌曲? ListView 还是 RecyclerView?

java - 线程快速排序