Проблема с потоками Java, используя Runnable или Thread - PullRequest
2 голосов
/ 08 ноября 2010

Я пытаюсь реализовать многопоточность, используя сортировку слиянием. У меня есть создание новых потоков в точке, где он разрезает массив пополам.
Массив сортируется в зависимости от: [размер массива] против [сколько раз я создаю новые темы] Например: массив будет отсортирован, если я позволю ему создать только два потока в массиве размером 70, но если я позволю ему создать 6, он вернется несортированным. Я подумал, что это может быть связано с тем, что потоки не были синхронизированы, но я использовал threadName.join ()

вот код: merge.java

import java.util.Random;

public class merge implements Runnable {
    int[] list;
    int length;
    int countdown;

    public merge(int size, int[] newList, int numberOfThreadReps, int firstMerge) {
        length = size;
        countdown = numberOfThreadReps;
        list = newList;
        if (firstMerge == 1)
            threadMerge(0, length - 1);
    }

    public void run() {
        threadMerge(0, length - 1);
    }

    public void printList(int[] list, int size) {
        for (int i = 0; i < size; i++) {
            System.out.println(list[i]);
        }
    }

    public void regMerge(int low, int high) {
        if (low < high) {
            int middle = (low + high) / 2;
            regMerge(low, middle);
            regMerge(middle + 1, high);
            mergeJoin(low, middle, high);
        }
    }

    public void mergeJoin(int low, int middle, int high) {
        int[] helper = new int[length];

        for (int i = low; i <= high; i++) {
            helper[i] = list[i];
        }

        int i = low;
        int j = middle + 1;
        int k = low;

        while (i <= middle && j <= high) {
            if (helper[i] <= helper[j]) {
                list[k] = helper[i];
                i++;
            } else {
                list[k] = helper[j];
                j++;
            }
            k++;
        }
        while (i <= middle) {
            list[k] = helper[i];
            k++;
            i++;
        }
        helper = null;
    }

    public void threadMerge(int low, int high) {
        if (countdown > 0) {
            if (low < high) {
                countdown--;
                int middle = (low + high) / 2;
                int[] first = new int[length / 2];
                int[] last = new int[length / 2 + ((length % 2 == 1) ? 1 : 0)];
                for (int i = 0; i < length / 2; i++)
                    first[i] = list[i];
                for (int i = 0; i < length / 2 + ((length % 2 == 1) ? 1 : 0); i++)
                    last[i] = list[i + length / 2];

                merge thread1 = new merge(length / 2, first, countdown, 0);// 0
                                                                            // is
                                                                            // so
                                                                            // that
                                                                            // it
                                                                            // doesn't
                                                                            // call
                                                                            // threadMerge
                                                                            // twice
                merge thread2 = new merge(length / 2
                        + ((length % 2 == 1) ? 1 : 0), last, countdown, 0);

                Thread merge1 = new Thread(thread1);
                Thread merge2 = new Thread(thread2);
                merge1.start();
                merge2.start();

                try {
                    merge1.join();
                    merge2.join();
                } catch (InterruptedException ex) {
                    System.out.println("ERROR");
                }

                for (int i = 0; i < length / 2; i++)
                    list[i] = thread1.list[i];
                for (int i = 0; i < length / 2 + ((length % 2 == 1) ? 1 : 0); i++)
                    list[i + length / 2] = thread2.list[i];

                mergeJoin(low, middle, high);
            } else {
                System.out.println("elsd)");
            }
        } else {
            regMerge(low, high);
        }
    }
}

proj4.java

import java.util.Random;

public class proj4 {
    public static void main(String[] args) {
        int size = 70000;
        int threadRepeat = 6;
        int[] list = new int[size];
        list = fillList(list, size);
        list = perm(list, size);
        merge mergy = new merge(size, list, threadRepeat, 1);
        // mergy.printList(mergy.list,mergy.length);
        for (int i = 0; i < mergy.length; i++) {
            if (mergy.list[i] != i) {
                System.out.println("error)");
            }
        }
    }

    public static int[] fillList(int[] list, int size) {
        for (int i = 0; i < size; i++)
            list[i] = i;
        return list;
    }

    public static int[] perm(int[] list, int size) {
        Random generator = new Random();
        int rand = generator.nextInt(size);
        int temp;
        for (int i = 0; i < size; i++) {
            rand = generator.nextInt(size);
            temp = list[i];
            list[i] = list[rand];
            list[rand] = temp;
        }
        return list;
    }

}

so TL; DR мой массив не сортируется многопоточным сортированием слиянием на основе размера массива и количества раз, когда я разделяю массив с помощью потоков ... почему это так?

1 Ответ

4 голосов
/ 21 сентября 2011

Ничего себе. Это было интересное упражнение в мазохизме. Я уверен, что вы пошли дальше, но я подумал о потомстве ...

Ошибка в коде в mergeJoin с аргументом middle. Это нормально для regMerge, но в threadMerge переданная середина равна (low + high) / 2 вместо (length / 2) - 1. Поскольку в threadMerge low всегда 0, а high равно length - 1, а массив first имеет размер (length / 2). Это означает, что для списков с нечетным числом записей он часто завершается ошибкой в ​​зависимости от рандомизации.

Существует также ряд проблем со стилем, которые значительно усложняют эту программу и приводят к ошибкам:

  • Код обходит размер массивов, когда в Java есть удобный вызов list.length, который был бы более простым и безопасным.
  • Код дублирует вычисления (см. length/2) в нескольких местах.
  • Код должен иметь возможность сортировки внутри массива без создания подмассивов.
  • Классы должны начинаться с заглавной буквы (Merge вместо merge)
  • firstMerge должно быть логическим
  • Код именует переменную Thread merge1 и переменную merge thread1. Глоток.
  • Конструктор merge, вызывающий threadMerge(0,length -1), странный. Я бы просто положил этот вызов после new обратного вызова в proj4. Тогда firstMerge можно удалить.
  • Я бы посоветовал переключиться на high, который будет равен максимальному значению вместо максимального Мы склонны думать как for (int i = 0; i < 10; i++) больше, чем i <= 9. Тогда код может иметь значение j от low до < middle и k от middle до < high. Лучшая симметрия.

Удачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...