`
liuwei1981
  • 浏览: 772401 次
  • 性别: Icon_minigender_1
  • 来自: 太原
博客专栏
F8258633-f7e0-30b8-bd3a-a0836a5f4de5
Java编程Step-by...
浏览量:161290
社区版块
存档分类
最新评论

总和的玩笑

阅读更多

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

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,初始化总和值的方法被执行了两次。

 

分享到:
评论
12 楼 Godlikeme 2007-04-23  
果然,如ls所说。又学到东西了,以前还一直以为static块最先初始化,然后是static成员变量,原来是顺序初始化,
11 楼 dovecat 2007-04-23  
Godlikeme 写道
to ls: 不ok,
你试试嘛.我刚刚试了的.只是把你说的意思表述清楚而已.HOHO~
10 楼 Godlikeme 2007-04-23  
to ls: 不ok,
9 楼 dovecat 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;

    }

  }

}
8 楼 Godlikeme 2007-04-23  
xly_971223 写道
楼主是想在类加载的时候就完成计算结果吧
为什么又在getSum()中调用方法 initializeIfNecessary()呢?
直接
public static int getSum(){

                return sum;

           }

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



恩,是的,需求这样实现比较奇怪。
7 楼 Godlikeme 2007-04-23  
jamesby 写道
initializeIfNecessary
已经用到了变量initialized 了啊,如果用到initialized 应该首先被初始化啊.

搞不懂JVM怎么工作的.


建议仔细阅读thinking in java 初始化?构造,那一章,
6 楼 抛出异常的爱 2007-04-23  
。。。。。。如果是业务就不能去掉
要去只能去掉staic块里的东西
5 楼 xly_971223 2007-04-22  
楼主是想在类加载的时候就完成计算结果吧
为什么又在getSum()中调用方法 initializeIfNecessary()呢?
直接
public static int getSum(){

                return sum;

           }

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

4 楼 jamesby 2007-04-22  
initializeIfNecessary
已经用到了变量initialized 了啊,如果用到initialized 应该首先被初始化啊.

搞不懂JVM怎么工作的.
3 楼 Godlikeme 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;

         }

 }

}
2 楼 Godlikeme 2007-04-21  
好像问题是这样之,可以跟踪下,static块最先初始化,初始化后sum =4950,initialized = true;
之后 static initialized初始化赋值=false;
再次调用的时候 再次计算sum=9900,initialized = true;

埃,在eclipse下好像没法对static块进行跟踪,jvm报错,没办法了。
1 楼 抛出异常的爱 2007-04-20  
锁用错了。。。

相关推荐

    ArcGIS教程:加权总和的工作原理

    在GIS分析中,ArcGIS提供了一系列工具来处理和综合地理数据,其中加权总和工具是一种重要的集成分析方法。这个工具允许用户结合多个输入栅格数据,每层数据代表一个特定的因素,通过分配相应的权重来形成一个综合...

    基于Matlab的使用sum函数计算矩阵、数组、向量元素总和.txt

    本资源包含基于Matlab的使用sum方法计算矩阵、数组、向量元素总和 包含 实例1:计算向量元素总和 实例2:计算矩阵每列元素的总和 实例3:计算矩阵每行元素的总和 实例4:计算数组特定切片元素(维度1*维度2)的总和 ...

    Excel模板年限总和法计提折旧表.zip

    年限总和法是一种会计折旧方法,用于估算固定资产在预计使用寿命内的累计折旧。这种方法假设资产在初期会更快地失去其价值,随着时间的推移,折旧速度逐渐减缓。Excel模板“年限总和法计提折旧表”是会计师、财务...

    C语言程序 计算所输入的整数n的1到n总和和平均数

    在本文中,我们将深入探讨如何使用C语言编写一个程序,以计算用户输入的整数n的1到n的总和及平均数。C语言是一种强大的、低级别的编程语言,广泛用于系统开发、软件工程和嵌入式系统。下面,我们先来理解程序的基本...

    java面试资料总和(最近更新)

    这份"java面试资料总和(最近更新)"包含了最新的面试题库,旨在帮助求职者准备各大开发公司的面试。 首先,Java基础是面试中不可或缺的部分。这包括对Java语法的深入理解,如面向对象编程概念(封装、继承、多态)...

    数组总和.html

    数组总和

    photoshop样式总和

    photoshop样式总和photoshop样式总和

    excel如何确定几个未知数之和刚好等于给定的总和值.docx

    "Excel 如何确定几个未知数之和刚好等于给定的总和值" 本文将引导您了解 Excel 中如何确定几个未知数之和刚好等于给定的总和值。该方法使用 RAND 函数和一些数学公式来实现。 一、RAND 函数 RAND 函数是 Excel 中...

    VBA源码:凑数-指定范围生成随机数总和等于指定值

    指定范围生成随机数,并且随机数总和等于指定值

    查看总和.xls

    查看总和.xls

    lvbo_谐波总和_有源滤波_

    标题“lvbo_谐波总和_有源滤波_”暗示我们讨论的是与谐波电流的计算以及如何通过有源滤波器进行补偿相关的内容。描述中提到的“整流桥电流中谐波总和的求法”是计算谐波的关键步骤,通常在设计谐波补偿器时需要用到...

    年数总和法.zip

    年数总和法,也称为年限总和折旧法,是一种在会计和财务领域中用于固定资产折旧的计算方法。这种方法假设资产的价值随着时间的推移而以递减的速度减少,其核心理念是每年的折旧额是根据资产的剩余使用年限来确定的,...

    路径总和.md

    路径总和.md

    组合总和.md

    组合总和.md

    制度总和.doc

    制度总和.doc

    长方体和正方体的棱长总和.doc

    在本节数学课《长方体和正方体的棱长总和》中,教师旨在帮助学生深入理解和掌握长方体与正方体的基本特征,并学会如何计算这两种立体图形的棱长总和。课程围绕以下几个核心知识点展开: 1. **长方体和正方体的特征*...

    js求数组总和、最大值、最小值、平均值、标准差.pdf

    本文将详细介绍 JavaScript 中数组统计函数的实现,包括数组总和、最大值、最小值、平均值和标准差的计算。通过对代码的解析和分析,我们将了解如何使用 JavaScript 实现数组的统计计算。 一、数组总和的计算 在...

    固定资产折旧年数总和法、双倍余额递减法培训课件.pptx

    固定资产折旧年数总和法、双倍余额递减法培训课件.pptx

    gridview footer实现求总和

    在GridView中添加Footer行并实现求总和的功能,对于数据分析和报表展示尤其有用。这个功能可以帮助用户快速查看表格数据的总计,无需手动计算。 要实现GridView的Footer行求总和,首先你需要在设计阶段设置GridView...

    Python语言基础项目案例:数值总和以及最大值.pptx

    在这个Python编程语言的基础项目案例中,我们关注的核心知识点是如何利用Python编写一个程序,该程序能够实现两个主要功能:计算用户输入的一系列数值的总和,以及找出这些数值中的最大值。下面将详细解释这个程序的...

Global site tag (gtag.js) - Google Analytics