论坛首页 入门技术论坛

总和的玩笑

浏览 6530 次
锁定老帖子 主题:总和的玩笑
该帖已经被评为新手帖
作者 正文
   发表时间:2007-04-20  

下面的类计算并缓存了一个总和,并且在另一个类中打印这个总和       

class Cache{

             static {

                   initializeIfNecessary();

              }

          private static int sum;

          public static int getSum(){

                initializeIfNecessary();

                return sum;

           }

         private static boolean initialized = false;

        private static synchronized void initializeIfNecessary(){

              if(!initialized){

                     for(int i=0;  i <  100;  i++  )

                         sum+=i;

                    initialized = true;

                  }

          }

        }

 

pubic class Client  {

    pubilc static void main(String[] args){

            System.out.println(Cache.getSum());

   }

 }

程序是一个典型的半开循环,应该打印出1到99的整数总和,即4950,但程序运行打印的为9900,是预期值的两倍。

程序在确保sum在使用之前就已经初始化这个问题上,遇到了麻烦。程序结合了惰性初始化和积极初始化,还使用上了同步,以确保缓存在多线程环境下也能工作,但程序无法完成预期的工作。

程序输出打印是控制标志initialized 的问题。qq上一个朋友问的一本书里的问题,我也找到那本书了,是惰性初始化(static初始化)的问题,控制标志在static完成初始化后又重新被构造器赋值为false,初始化总和值的方法被执行了两次。

 

   发表时间:2007-04-20  
锁用错了。。。
0 请登录后投票
   发表时间:2007-04-21  
好像问题是这样之,可以跟踪下,static块最先初始化,初始化后sum =4950,initialized = true;
之后 static initialized初始化赋值=false;
再次调用的时候 再次计算sum=9900,initialized = true;

埃,在eclipse下好像没法对static块进行跟踪,jvm报错,没办法了。
0 请登录后投票
   发表时间:2007-04-21  
应该写成这样子

class Cache{

    static {

          initialized=false;   	//init here...
          initializeIfNecessary();

     }

 private static int sum;

 public static int getSum(){

       initializeIfNecessary();

       return sum;

  }

private static boolean initialized;

private static synchronized void initializeIfNecessary(){

     if(!initialized){

            for(int i=0;  i <  100;  i++  )

                sum+=i;

           initialized = true;

         }

 }

}
0 请登录后投票
   发表时间:2007-04-22  
initializeIfNecessary
已经用到了变量initialized 了啊,如果用到initialized 应该首先被初始化啊.

搞不懂JVM怎么工作的.
0 请登录后投票
   发表时间:2007-04-22  
楼主是想在类加载的时候就完成计算结果吧
为什么又在getSum()中调用方法 initializeIfNecessary()呢?
直接
public static int getSum(){

                return sum;

           }

就行了吧
这样的话initializeIfNecessary()方法上的synchronized也可以去掉了

0 请登录后投票
   发表时间:2007-04-23  
。。。。。。如果是业务就不能去掉
要去只能去掉staic块里的东西
0 请登录后投票
   发表时间:2007-04-23  
jamesby 写道
initializeIfNecessary
已经用到了变量initialized 了啊,如果用到initialized 应该首先被初始化啊.

搞不懂JVM怎么工作的.


建议仔细阅读thinking in java 初始化?构造,那一章,
0 请登录后投票
   发表时间:2007-04-23  
xly_971223 写道
楼主是想在类加载的时候就完成计算结果吧
为什么又在getSum()中调用方法 initializeIfNecessary()呢?
直接
public static int getSum(){

                return sum;

           }

就行了吧
这样的话initializeIfNecessary()方法上的synchronized也可以去掉了



恩,是的,需求这样实现比较奇怪。
0 请登录后投票
   发表时间:2007-04-23  
初始化顺序导致的.
应该先定义,然后再使用.
只须把
static {
    initializeIfNecessary();
  }

挪个窝就OK了.

LZ的写法直接引用了定义的initialized变量default 就是false,并且在
initializeIfNecessary()方法中改写了变量值,但是后来JVM又碰到
private static boolean initialized =false这句.
当然出现运行两次的情况.
class Cache {

  private static int sum;

  public static int getSum() {

    initializeIfNecessary();

    return sum;

  }

  private static boolean initialized = false;
  // 挪个窝,放到这个位置!
  static {
    initializeIfNecessary();
  }

  private static synchronized void initializeIfNecessary() {

    if (!initialized) {

      for (int i = 0; i < 100; i++)

        sum += i;

      initialized = true;

    }

  }

}
0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics