【问题标题】:concurrent Threads Merge Sort并发线程合并排序
【发布时间】:2015-10-25 14:39:08
【问题描述】:

我必须编写一个并发的合并排序应用程序。每次数组被拆分时,我都必须为右半部分创建一个新线程(最大线程数为 5 -> 所以 5 次),这将继续 Mergesort 算法。

这是我的程序:

class Mergesorts implements Runnable{

    private int[] internal;

    Mergesorts(int[] arr) {
        internal = arr;
    }

    private void processCommand(int [] array) {
        if (array.length > 1) { 
            int[] left = leftHalf(array);
            int[] right = rightHalf(array);
            processCommand(left);
            processCommand(right);
            merge(array, left, right);
        }
    }

    public int[] rightHalf(int[] array) {
        int size1 = array.length / 2;
        int size2 = array.length - size1;
        int[] right = new int[size2];
        for (int i = 0; i < size2; i++) {
            right[i] = array[i + size1];
        }
        return right;
    }

    public void run() {
        processCommand(internal);
    }
}

如何重写我的代码以按上述方式同时排序?

如何编辑我的代码,使其最多只能创建 5 个线程而不是更多?

private void processCommand(int [] array) {
    if (array.length > 1) {


        int[] right = rightHalf(array);
        int[] left = leftHalf(array);


        Mergesorts worker2 = new Mergesorts(right);
        Thread s = new Thread(worker2);
        s.start();

        processCommand(left);

        try {
            s.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        merge(array, left, right);}

}

【问题讨论】:

  • 问题是什么?到底是谁在支持一个问题......这不是一个问题?!
  • 问题是我应该在我的代码中的哪个位置创建继续执行相同算法的新线程
  • 我希望 SO 要求您在发布之前进行某种测试。这样我们就不会有这些半途而废的问题。诱使提问者将问题表述为可回答的形式需要不必要的时间。
  • @Merve 每次将数组一分为二时,您都需要创建一个新线程。前半部分可以继续处理前半部分,新线程开始处理后半部分。
  • 请在此处提供足够的演示或想法以获得解决方案。

标签: java multithreading concurrency mergesort


【解决方案1】:

在 processCommand() 方法中启动新线程,而不是在 rightHalf() 方法中。如果您有可用的线程,那么代替调用 processCommand(right) 的行,在 right 上构造一个新的 Mergesorts 对象并使用它启动一个线程。不要忘记在线程上调用 join() 以确保它在合并之前完成。

为了提高并行度,可以先在数组的右半边启动新线程,再处理数组的左半边,这样两者是同时完成的——即将processCommand(left)移到block之后要么执行 processCommand(right) 要么启动一个新线程。 join() 调用应该在两半完成之后,但在合并之前。

编辑:你越来越近了;要解决您的评论,您需要这样的东西:

private void processCommand(int [] array) {
    if (array.length <= 1)
        {return;}

    int[] left = leftHalf(array);
    int[] right = rightHalf(array);
    Thread rightThread = null;

    if (b <= 5) {
        ++b;
        Mergesorts worker = new Mergesorts(right);
        rightThread = new Thread(worker);
        rightThread.start();
    } else {
        processCommand(right);
    }

    processCommand(left);

    if (null != rightThread) {
        try {
            rightThread.join();
            b--
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            // better error handling would be good
        }
    }

    merge(array, left, right);
}

b 也需要是可变的,以确保不同的线程可以看到当前正在执行的线程数。

【讨论】:

  • 我不能把 join() 调用放在两半之后,因为那样 s 不能被解析,顺便说一句。为什么我的代码会创建超过 5 个线程?你能帮帮我吗!
  • 你越来越近了。在我的答案中添加了一些代码以澄清。
  • 我在 Mergesorts 类实现 Runnable{ private volatile int b=0;但它仍然创建了 5 个以上的线程 :(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-01
  • 2016-04-07
  • 1970-01-01
  • 1970-01-01
  • 2019-08-15
  • 1970-01-01
  • 2021-04-01
相关资源
最近更新 更多