2016-12-02 85 views
-4
package newpackage; 

import java.util.logging.Level; 
import java.util.logging.Logger; 

class test { 

    public int in = 0; 

    void helper() { 

     Thread t1 = new Thread(
       () 
       -> { 

      add(); 

     } 
     ); 

     Thread t2 = new Thread(
       () 
       -> { 

      add(); 

     } 
     ); 
     t1.start(); 
     t2.start(); 
     try { 
      t1.join(); 
      t2.join(); 
     } catch (InterruptedException ex) { 
      Logger.getLogger(test.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 

    void add() { 
     for (int i = 0; i < 40; i++) { 
      in += i; 
      try { 
       Thread.sleep(50); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(test.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
    } 

} 

public class Main { 

    public static void main(String[] args) { 
     test a = new test(); 
     a.helper(); 
     System.out.println(a.in); 
    } 
} 

我想要的是從不同線程同時運行同一個方法。java中的多線程方法

但是上面給出的代碼沒有給出正確的結果,它給出的輸出小於1560(780 + 780)。我該如何實現這一點?

在此先感謝。

+2

重新獲得「正確的結果」,您的期望輸出是什麼,以及您觀察到的輸出是什麼?此外,你的方法什麼都不做 - 請發佈真實的代碼,我們可以編譯,測試和修改的代碼。 –

+4

「沒有給出正確的結果」我認爲你的意思是它沒有給出你期望的結果,因爲它絕對符合Java規範所說的。你認爲它應該做什麼,它做了什麼呢? –

+0

@AndyTurner對不起。爲了簡單起見,我這樣做了。現在編輯。 –

回答

1

你已經遇到了併發程序的一個經典問題。無法正確同步的可變共享狀態。您的變量in由兩個線程同時修改,而且i += 1操作不是原子操作。在現實中發生的事情是:

int temp = i + 1; 
i = temp; 

現在的問題是這兩個線程同時運行,所以會發生什麼是這樣的:

// assuming i == 3 
int temp = i + 1; // Thread 1, temp == 4 
int temp = i + 1; // Thread 2, temp == 4 
i = temp; // Thread 2, i == 4 
i = temp; // Thread 1, i == 4 

正如你可以看到,我們增加了兩次,但我只有而且由於變量不是易失性的,或者任何線程中沒有可見性保證,也就是說,如果線程1修改了變量,那麼JVM不保證使該變更對任何其他讀取該變量的線程都可見。

爲了正確地做到這一點,您需要使用某種同步輔助,最簡單的方法是使用​​塊。然而,在這種情況下,這會失去並行添加事物的目的,因爲同步會使事情順序有效地運行,並帶來一些開銷。

如果您真的想要並行添加東西,請查看Java 8 Streams或Java 7中的Fork-Join Framework。但是,請注意,這樣做只會支付足夠大的數據集,因爲並行運行總是會有一些開銷。

+0

謝謝。得到它了 。那麼如果我的add()函數不能在同一個對象/變量上工作呢?說我的add()函數接受fileName的參數,然後寫入它。所以如果我從不同的線程傳遞兩個不同的文件名到相同的函數,會不會有任何形式的腐敗? –

+0

不,寫入單獨文件可以從不同線程並行完成,儘管最終這取決於底層文件系統。 – diesieben07