java - 线程快速排序

标签 java multithreading quicksort executorservice

你好,我以前从未尝试过使用线程,这是我的第一次尝试,但它并没有停止,正常的版本有效。 如果我删除 awaitTermination 它看起来像工作但我需要方法在它全部整理出来时完成(双关语 XD)。 你能告诉我我做错了什么吗? 谢谢。

public class Sorting {

  private Sorting() {};

  private static Random r = new Random();
  private static int cores = Runtime.getRuntime().availableProcessors();
  private static ExecutorService executor = Executors.newFixedThreadPool(cores);

  public static void qsortP(int[] a) {
    qsortParallelo(a, 0, a.length - 1);
  }

  private static void qsortParallelo(int[] a, int first, int last) {
    while (first < last) {
      int p = first + r.nextInt(last - first + 1);
      int px = a[p];
      int i = first, j = last;
      do {
        while (a[i] < px)
          i++;
        while (a[j] > px)
          j--;
        if (i <= j) {
          scambia(a, i++, j--);
        }
      } while (i <= j);
      executor.submit(new qsortThread(a, first, j));
      first = i;
    }
    try {
      executor.awaitTermination(1, TimeUnit.DAYS);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

  private static void scambia(int[] a, int x, int y) {
    int temp = a[x];
    a[x] = a[y];
    a[y] = temp;
  }

  public static class qsortThread implements Runnable {
    final int a[], first, last;

    public qsortThread(int[] a, int first, int last) {
      this.a = a;
      this.first = first;
      this.last = last;
    }

    public void run() {
      qsortParallelo(a, first, last);
    }
  }
}

最佳答案

与其等待整个执行程序服务终止(这可能根本不是您想要的),您应该保存 executor.submit() 返回的所有 Future 并等待它们全部完成(例如,通过对它们调用“get()”)。

尽管在 qsortParallelo() 方法中这样做很诱人,但这实际上会因线程池耗尽而导致死锁:父任务会占用等待子任务的工作线程完成,但子任务永远不会被安排运行,因为没有可用的工作线程。

所以你必须首先将所有的Future对象收集到一个并发集合中,将结果返回给qsortP()并在那里等待Futures 完成。

或者使用 ForkJoinPool,它专为此类任务而设计,可以为您完成所有繁重的工作。从应用程序代码递归地向执行器提交任务通常不是一个好主意,很容易出错。


顺便说一句,您的代码现在死锁的原因是每个工作线程都卡在 executor.awaitTermination() 中,从而阻止了执行程序服务的终止。

一般来说,设计和调试多线程应用程序的两个最有用的工具是:

  1. 线程转储。您可以使用 jstack 生成它、VisualVM 或任何其他工具,但它在死锁情况下非常宝贵,它可以让您准确了解线程正在(未)发生的事情。
  2. 一支笔,一张纸,画一张老式的泳道图。

关于java - 线程快速排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29806635/

相关文章:

c# - 如何将 Log4Net 包装类作为单例类?

java - 线程和按钮 : How to restart the program after its finished running

java - 如果输入的值错误,如何为 AutoCompleteTextView 设置焦点

java - 如何将一种语言(例如 python)绑定(bind)到另一种语言(例如 C++)?

java - 输出 "println"这样的命令是什么原因?如何在这段代码中初始化对象?

java - Linux Java 开发人员可以在同一个包中创建名称仅大小写不同的类吗?

c# - 清理散落着 InvokeRequired 的代码

c++ - 需要使用c++获取进程内存

java - 快速排序困惑

java - 快速排序永不停歇