2016-12-02 111 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