2012-07-26 87 views
1

这个主要给予一个ExecutorService 1000个runnables(测试者),他们所做的全部就是睡眠10毫秒,然后向静态计数器加1,主要是等待直到所有执行都完成了,但是计数器起了一些作用970处决......为什么?ExecutorService没有完成它的工作?

public class Testit { 
    public static void main (String arg[]) { 
     int n=1000; 
     ExecutorService e1 = Executors.newFixedThreadPool(20); 
     for (int i=0 ;i <n ;i++) { 
      e1.execute(new Tester()); 
     } 
     e1.shutdown(); 
     try { 
      e1.awaitTermination(1, TimeUnit.DAYS); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     System.out.println("Executed "+Tester.tester()+" Tasks."); 
    } 
} 

和Tester类:

public class Tester implements Runnable { 
    public static long tester=0; 
    @Override 
    public void run() { 
     try { 
      Thread.sleep(10); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     finally { tester++; } 
    } 
    public static long tester() { 
     long temp=tester; 
     tester=0; 
     return temp; 
    } 
} 

编辑

问题解决了:

finally { synchronized (lock) {tester++;} } 

感谢JB Nizet!

+1

如果JB的答案帮助你解决了你的问题,你应该将它标记为已接受... – 2012-07-26 09:42:13

+0

http://en.wikipedia.org/wiki/Race_condition – 2012-07-26 09:42:42

+0

@Louis Wasserman我会,我不能只是 – 2012-07-26 09:43:25

回答

6

由于您不同步对计数器的访问,并且因为写入long不是原子性的,并且++也不是,所以两个并发线程包含计数器可能会导致完全不一致的结果或仅导致一个而不是2.

改为使用AtomicLong,并在此AtomicLong上调用incrementAndGet()

+0

正在使用AtomicLong那么更好的方法就是在编辑时写一个简单的同步块? – 2012-07-26 09:42:58

+1

AtomicLong速度更快,是的,因为它是无锁的。它也更清楚地表达了意图。有关详细信息,请参阅http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/atomic/package-summary.html – 2012-07-26 09:54:51

+0

@GPS:不,我对GWT一无所知。 – 2012-07-26 09:58:18