锁定老帖子 主题:总和的玩笑
该帖已经被评为新手帖
|
|
---|---|
作者 | 正文 |
发表时间: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,初始化总和值的方法被执行了两次。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-04-20
锁用错了。。。
|
|
返回顶楼 | |
发表时间:2007-04-21
好像问题是这样之,可以跟踪下,static块最先初始化,初始化后sum =4950,initialized = true;
之后 static initialized初始化赋值=false; 再次调用的时候 再次计算sum=9900,initialized = true; 埃,在eclipse下好像没法对static块进行跟踪,jvm报错,没办法了。 |
|
返回顶楼 | |
发表时间: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; } } } |
|
返回顶楼 | |
发表时间:2007-04-22
initializeIfNecessary
已经用到了变量initialized 了啊,如果用到initialized 应该首先被初始化啊. 搞不懂JVM怎么工作的. |
|
返回顶楼 | |
发表时间:2007-04-22
楼主是想在类加载的时候就完成计算结果吧
为什么又在getSum()中调用方法 initializeIfNecessary()呢? 直接 public static int getSum(){ return sum; } 就行了吧 这样的话initializeIfNecessary()方法上的synchronized也可以去掉了 |
|
返回顶楼 | |
发表时间:2007-04-23
。。。。。。如果是业务就不能去掉
要去只能去掉staic块里的东西 |
|
返回顶楼 | |
发表时间:2007-04-23
jamesby 写道 initializeIfNecessary
已经用到了变量initialized 了啊,如果用到initialized 应该首先被初始化啊. 搞不懂JVM怎么工作的. 建议仔细阅读thinking in java 初始化?构造,那一章, |
|
返回顶楼 | |
发表时间:2007-04-23
xly_971223 写道 楼主是想在类加载的时候就完成计算结果吧
为什么又在getSum()中调用方法 initializeIfNecessary()呢? 直接 public static int getSum(){ return sum; } 就行了吧 这样的话initializeIfNecessary()方法上的synchronized也可以去掉了 恩,是的,需求这样实现比较奇怪。 |
|
返回顶楼 | |
发表时间: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; } } } |
|
返回顶楼 | |