2012-05-22 75 views
0

該代碼從不同的蒸汽數據中讀取數字,並輸出整個和。這段代碼有什麼問題嗎?我該如何解決它?java線程不同流

public class Thr extends Thread{ 
static int numThr=100, sum=0; 
private int num; 
private Thr(int num){this.num =num;} 
public void run() { 
    int k = IntegerReader.get(num); 
    int count=0; 
    while(k>0) { 
     if(count%numThr==num) sum+=k; 
     count++; 
     k=IntegerReader.get(num); 
    } 
} 
public static void main(String[] a) throws Exception { 
    thr[] st =new thr[numThr]; 
    for(int i=0; i<numThr; i++) st[i] = new Thr(i); 
    for(int i=0; i<numThr; i++) st[i].start(); 
    System.out.println("sum = "+sum); 
} 
} 
+2

''有沒有什麼問題'這不是我們在這裏回答的問題的類型。 –

+0

你爲什麼認爲這段代碼有問題?什麼不按預期工作?什麼是「IntegerReader」? – Jeffrey

+2

'我的車有什麼問題,我該如何解決它?' –

回答

1

馬上有很多事情是錯的。

  1. 總和被多個線程之間共享和多線程這意味着你可以得到不一致的值,因爲增加的數值是一個原子操作遞增。

    這個最簡單的解決方法是求和的聲明更改爲: private static AtomicInteger sum = new AtomicInteger(0);

    ,並添加到它是這樣的: sum.getAndAdd(k)

  2. 「numThr」在多個線程之間共享,並宣讀由多個線程。由於numThr不是最終的,同步的或易失性的,因此不能保證其他線程將看到它的值已被初始化。 numThr應聲明爲private static final int numThr=100

  3. 您的System.out.println("sum = "+sum);將在您的線程完成執行之前打印。在打印總和之前,您需要在您的線程上「加入」(即等待它們完成)。在您的sysout之前添加:for(int i=0; i<numThr; i++) st[i].join();

我想你應該閱讀Java內存模型和Java中的併發性。 這裏是一個基本的教程,但你真的需要一本關於這個問題的書: http://docs.oracle.com/javase/tutorial/essential/concurrency/

+0

我有點出來練習用java ..爲什麼不聲明總和爲'volatile'? – mkoryak

+0

因爲他正在遞增變量,所以它不能是簡單易失性的,並且當和增加時有三個操作發生。一個有問題的情況可能是:線程1讀取sum(sum = 0),然後被線程2搶佔。線程2讀取sum(sum = 0),增加和寫入sum(sum = 1)。線程1恢復,增加它爲sum(0)讀取的值,然後寫入sum(sum = 1)。 –

+0

謝謝你馬特,非常有幫助 –

0

是的,這段代碼有幾個錯誤。一種解決方法是花時間閱讀並理解Java tutorial。另一種方法是要求別人爲你解決這個問題,但要注意,這種事情在這裏不會很好。