简体   繁体   English

螺纹快速排序

[英]Threaded quicksort

Hello I've never tried using threads before, this is my first attempt but it doesn't stop, The normal verion works. 您好我以前从未尝试过使用过线程,这是我的第一次尝试,但它并没有停止,正常的版本有效。 if I remove awaitTermination it looks like it works but I need the method to finish when it's all sorted out(pun intended XD). 如果我删除awaitTermination它看起来像它的工作但我需要该方法完成它全部整理(双关语意图XD)。 Can you tell me what I did wrong? 你能告诉我我做错了什么吗? Thank you. 谢谢。

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);
    }
  }
}

You are calling executor.awaitTermination inside a Thread which was launched by your executor . 您在executor.awaitTermination启动的Thread中调用executor Thread will not stop until executor comes out of the awaitTermination and executor will not come out of awaitTermination until the Thread terminates. Thread不会停止,直到executor退出awaitTermination并且executor将不会退出awaitTermination直到Thread终止。 You need to move this code: 您需要移动此代码:

try {
  executor.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
  e.printStackTrace();
}

into the end of qsortP method. 进入qsortP方法的最后。

Instead of waiting for termination of the entire executor service (which probably isn't what you want at all), you should save all the Future s returned by executor.submit() and wait until they're all done (by calling 'get()` on them for example). 你应该保存executor.submit()返回的所有Future ,而不是等待终止整个执行程序服务(可能根本不是你想要的),并等到它们全部完成(通过调用'get ()`例如,他们)。

And though it's tempting to do this in the qsortParallelo() method, that would actually lead to a deadlock by exhaustion of the thread pool: parent tasks would hog the worker threads waiting for their child tasks to complete, but the child tasks would never be scheduled to run because there would be no available worker threads. 尽管在qsortParallelo()方法中这样做很有吸引力,但这实际上会导致线程池耗尽导致死锁:父任务会占用工作线程等待子任务完成,但子任务永远不会计划运行,因为没有可用的工作线程。

So you have to collect all the Future objects into a concurrent collection first, return the result to qsortP() and wait there for the Future s to finish. 因此,您必须首先将所有Future对象收集到并发集合中,将结果返回到qsortP()并等待Future s完成。

Or use a ForkJoinPool , which was designed for exactly this kind of task and does all the donkey work for you. 或者使用ForkJoinPool ,它专为完成此类任务而设计,并为所有驴工作。 Recursively submitting tasks to an executor from application code is generally not a very good idea, it's very easy to get it wrong. 从应用程序代码递归地向执行程序提交任务通常不是一个好主意,它很容易弄错。


As an aside, the reason your code is deadlocked as it is is that every worker thread is stuck in executor.awaitTermination() , thereby preventing the termination of the executor service. 顺便说一下,你的代码死锁的原因是每个工作线程都停留在executor.awaitTermination() ,从而阻止了执行程序服务的终止。

In general, the two most useful tools for designing and debugging multi-threaded applications are: 通常,设计和调试多线程应用程序的两个最有用的工具是:

  1. A thread dump. 线程转储。 You can generate that with jstack , VisualVM or any other tool, but it's invaluable in deadlock situations, it gives you an accurate image of what's (not) going on with your threads. 您可以使用jstack ,VisualVM或任何其他工具生成它,但它在死锁情况下非常有用,它可以准确地显示线程中(不)的内容。
  2. A pen, a piece of paper and drawing a good old fashioned swimlane chart. 一支笔,一张纸,绘制一个很好的老式泳道图表。

The mistake in this code is simply the while-loop in qsortParallelo . 这段代码中的错误只是qsortParallelo的while循环。 first and last are never modified. 从不修改firstlast Apart from that you don't need the while-loop, since you already do that the further sorting in the executor. 除此之外,您不需要while循环,因为您已经在执行程序中进行了进一步排序。 And you'll need to start another task for the second half of the array. 而且你需要为数组的后半部分启动另一个任务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM