首页 > 解决方案 > 多线程程序永远不会停止执行

问题描述

我有一个多线程快速排序算法,女巫运行正确,但永远不会停止执行。

我尝试在任何地方添加返回声明,但没有任何帮助。

完成后如何阻止所有线程运行?有没有办法让线程在完成后终止其自身?

public class Parallel {
    private static final int numberOfThreads = Runtime.getRuntime().availableProcessors();
    private static final int fallback = 2;
    private static Executor pool = Executors.newFixedThreadPool(numberOfThreads);
    //public static int[] numberArray;


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

        try {
          synchronized (count) {
            count.wait();

          }
        } catch (InterruptedException e) {       
          e.printStackTrace();
        }
      }

    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) {
            // AtomicInteger.getAndDecrement() returns the old value. If the old value is 1, then we know that the actual value is 0.
            if (count.getAndDecrement() == 1)
                count.notify();                         
          }
          return;
        }

        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 * numberOfThreads) {
            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));
            }
          }
        }

      }

还有我的主要功能

 public static void main(String args[]) {
        Random rand = new Random();
        int length = 100000;

        int[] parallelArray = new int[length];

        for (int i = 0; i < length; i++) {
            int temp = rand.nextInt(length);
            parallelArray[i] = temp;            
        }
        sort(parallelArray);
        boolean t = check(parallelArray);
        System.out.println(t);
    }

测试代码是否排序的函数。

public static boolean check(int[] A) {
        for (int i = 0; i < A.length - 1; i++) {
            // System.out.print(" " + A[i]);
            if (A[i] < A[i + 1]) {
                return false;
            }
        }
        return true;
    }

标签: javaeclipsemultithreadingquicksort

解决方案


当您使用 a 时,ExecutorService您需要ExecutorService.shutdown()在所有任务提交后调用,然后您需要通过调用等待池关闭ExecutorService.awaitTermination()并提供等待时间作为参数。这是因为池由非守护线程组成,如果非守护线程仍在运行,jvm 不会退出。

因此,将 this 更改为使用ExecutorServicefromExecutor来启用挂钩:

private static ExecutorService pool = Executors.newFixedThreadPool(numberOfThreads);

然后shutdown()finally块中调用:

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

        try {
            synchronized (count) {
                count.wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            pool.shutdown(); //call shutdown() here
            try {
                pool.awaitTermination(5, TimeUnit.MINUTES); //wait for 5 minutes
            }catch (InterruptedException ie) {
                ie.printStackTrace();
            }
        }
    }

finally调用部分调用shutdown()以启动池中线程的有序关闭,并且由于shutdown调用没有阻塞,awaitTermination()因此必须调用调用线程以等待关闭过程完成。

5分钟等待是不是有点太多了?

调用awaitTermination不一定要等待整整五分钟。5 分钟是等待的最长时间,而不是最短时间。对于 Javadoc:

阻塞直到所有任务在关闭请求后完成执行,或者发生超时,或者当前线程被中断,以先发生者为准。


推荐阅读