2010-11-08 30 views
2

我想使用合併排序實現多線程。我在創建新線程的時候將數組減半。
該數組排序取決於: [數組的大小] vs [我創建新線程的次數] 例如:如果我讓它在大小爲70的數組上創建僅兩個線程,數組將被排序,但如果我讓它創建6,它會回來unsorted。有一兩件事我想這可能是是線程不同步時間,但我用threadName.join()Java線程問題,使用Runnable或線程

這裏是一些代碼: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我的數組沒有通過基於數組大小和使用線程拆分數組次數的多線程合併排序進行排序......爲什麼是這樣?

回答

4

哇。這在受虐狂中是一個有趣的練習。我相信你已經走了,但我想爲後人...

代碼中的錯誤在mergeJoinmiddle參數。這適用於regMerge,但在threadMerge中間傳入的是(low + high)/2而不是(length/2) - 1。由於在threadMergelow總是0而highlength - 1而且first數組的大小爲(length/2)。這意味着對於具有奇數個條目的列表,它通常會因隨機化而失敗。

也有一些作風問題,這使得這個程序顯著更復雜,容易出錯:

  • 代碼傳遞一個大小的數組左右時,Java有一個方便的list.length調用,它會更簡單更安全。
  • 該代碼在許多地方重複計算(請參閱length/2)。
  • 代碼應該能夠在數組內部排序而不需要創建子數組。
  • 類應以大寫字母(的Merge代替merge
  • firstMerge開始應該是一個布爾
  • 的代碼名稱Thread可變merge1merge可變thread1。咕嘟咕嘟。
  • 構造函數merge調用threadMerge(0,length -1)很奇怪。我會在new回撥proj4之後撥打該電話。然後firstMerge可以被刪除。
  • 我會考慮切換到high超過最大值而不是最大值。我們傾向於認爲像for (int i = 0; i < 10; i++)多於i <= 9。然後代碼可以從low< middlekmiddle< high。更好的對稱性。

祝你好運。