2012-07-29 102 views
1

我有以下的Java代碼:Java多線程等到子線程死

import java.io.*; 
class Global{ 
public static int a = 0 ; 
public static int b = 0 ; 
} 
public class Example{ 
public static void main(String args[]) { 
    try { 
     FileOutputStream fos = new FileOutputStream("1.dat"); 
     DataOutputStream dos = new DataOutputStream(fos); 

     for (int i = 0; i < 20000; i++) { 
      dos.writeInt(i); 
     } 
     dos.close(); 

     FileOutputStream fos1 = new FileOutputStream("2.dat"); 
     DataOutputStream dos1 = new DataOutputStream(fos1); 

     for (int i = 20000; i < 40000; i++) { 
      dos1.writeInt(i); 
     } 
     dos1.close(); 

     Exampless.createArray(20000); //static method call to set the static arr variable 
     Exampless ex1 = new Exampless("1.dat"); //found number of matches in file 
     Exampless ex2 = new Exampless("2.dat"); 
     Thread t1 = new Thread(ex1); 
     Thread t2 = new Thread(ex2); 
     t1.start(); 
     t1.join(); 
     t2.start(); 
     t2.join(); 
     System.out.println("No. of Matches: " + (Global.a + Global.b)); 

    } catch (Exception e) { 
     System.err.println("Error: " + e.getMessage()); 
    } 
} 
} 

class Exampless implements Runnable { 

public static int[] arr = new int[20000]; 
public String _name; 

public Exampless(String name) { 
    this._name = name; 
} 

static void createArray(int z) { 
    for (int i = z; i < z + 20000; i++) { 
     arr[i - z] = i; 
    } 
} 

public void run() { 
    try { 
     int cnt = 0; 
     FileInputStream fin = new FileInputStream(_name); 
     DataInputStream din = new DataInputStream(fin); 
     for (int i = 0; i < 20000; i++) { 
      int c = din.readInt(); 
      if (c == arr[i]) { 
       cnt++; 
      } 
     } 
     System.out.println("File name: " + _name + " No. of Matches: " + cnt); 
     if(_name == "1.dat") 
      Global.a = cnt ; 
     else if(_name == "2.dat") 
      Global.b = cnt ; 
    } catch (Exception e) { 
     System.err.println("Error: " + e.getMessage()); 
    } 
} 

} 

有我試圖運行Exampless類run方法平行。但是,我想讓主線程等到子線程完成後,我已經使用了join。但是,它會一個接一個地執行線程。任何人都可以幫我解決這個問題嗎?另一點是,我想在兩個線程中共享一個變量(命名爲cnt,它在文件中找到了匹配的數目),我使用Global類來完成匹配的總數。還有其他好的解決方案嗎?

回答

4

t1.join()等待,直到T1完成,所以你需要反轉的2線:

t1.start(); 
t2.start(); 
t1.join(); 
t2.join(); 

但是,你會使用高級別的併發包裝會更好,並且通常是ExecutorService

ExecutorService executor = Executors.newFixedThreadPool(2); 
executor.submit(ex1); 
executor.submit(ex2); 
executor.shutdown(); 

你的下一個問題:

我想共享一個變量(命名爲cnt,它在文件中找到了匹配的數量),這兩個線程使用Global類來完成匹配的總數。還有其他好的解決方案嗎?

你在做什麼不是線程安全的,除非這些變量是不穩定的。如果它們不是,您的主打印中的打印可能不會打印這些變量的最新值。

更好的解決方案是讓Exampless執行Callable而不是Runnable,在這種情況下,您可以返回一個值。

然後你可以檢索由執行返回的未來價值:

Future<Integer> future1 = executor.submit(ex1); 
Future<Integer> future2 = executor.submit(ex2); 

count1 = future1.get(); 
count2 = future2.get(); 

PS:你需要添加錯誤圍繞future.get()電話

處理代碼
+0

非常感謝。你可以好好修改一下上面的代碼,這樣做意味着讓代碼線程安全。因爲「import java.util.concurrent」和「implements callable」說沒有找到這樣的方法和類。 – Arpssss 2012-07-29 20:23:02

+0

@Arpssss我已經添加了一個鏈接到Callable接口 - 它就像一個runnable,除了你沒有'public void run'方法。在你的情況下,你將實現'Callable '因爲你需要返回一個整數,並且實現的方法是'public Integer call()'。您返回的價值將成爲您的計數。如果使用'future.get()'讀取它,則該值以線程安全的方式返回,因此不需要添加任何其他內容。 – assylias 2012-07-29 20:26:50

1

您是否曾嘗試在加入前先啓動兩個線程?

t1.start(); 
    t2.start(); 
    t1.join(); 
    t2.join();