3.4  不可变性 为了满足同步的需要,另一种方法是使用不可变对象[EJ Item13]。到目前为止,几乎所有我们已经描述过的原子性与可见性的危险,比如访问过期数据,未及时更新或者观察一个处于不一致状态的对象,它们都产 生于多线程下各种难以预测的行为协同工作,多个线程总试图同时访问相同的可变状态。如果对象的状态不能被修改,这些风险与复杂度就自然而然地消失了。 创建后状态不能被修改的对象叫做不可变对象。不可变对象天生是线程安全的。它们的常量(域)是在构造函数中创建的。既然它们的状态无法被修改,这些常量永远不会变。 不可变对象永远是线程安全的。 ...
使用多个 Java 线程之间共享数据的缺点在于数据访问必须同步,从而避免出现不一致的内容视图,后者可能会导致应用程序失败。例如,Hashtable 类的 put() 和 get() 方法是同步的。因为需要实现同步,所以 put() 和 get() 方法在执行时将同时单独地访问数据;否则,应用程序数据结构可能会被破坏。 当某个应用程序的线程频繁访问这些方法,导致线程出现阻塞时,这些方法的同步点将成为瓶颈。每次只能有一个线程获得内容的访问权。而其他线程必须等 待。如果线程出现排队等候(如果不是这样,线程能够进行其他有用操作),性能和吞吐量将下降。当性能分析显示同步方法实际上 ...
1、调用顺序: JAVA类首次装入时,会对静态成员变量或方法进行一次初始化,但方法不被调用是不会执行的,静态成员变量和静态初始化块级别相同,非静态成员变量和非静态初始化块级别相同。 先初始化父类的静态代码--->初始化子类的静态代码--> (创建实例时,如果不创建实例,则后面的不执行)初始化父类的非静态代码--->初始化父类构造函数--->初始化子类非静态代码--->初始化子类构造函数 2 、类只有在使用New调用创建的时候才会被JAVA类装载器装入 3、创建类实例时,首先按照父子继承关系进行初始化 4、类实例创建时候,首先初始 ...
本文探讨了一个常见的线程方面的危险:在构造过程中,允许this引用脱逃 。 这个看上去没什么危害的做法,实际上可能在Java程序中造成无法预料和不期望的结果。 “this引用逃脱”造成问题的本质就是,外部线程获得了一个没有完全构筑的对象! 测试和调试多线程程序是非常困难的,因为并发性方面的危险常常是以不一致的方式显现出来。多数线程问题都是很难预料的,设置在某些平台上(如单处 理器系统),或者低于一定的负载,问题可能根本就不出现。 由于测试多线程程序的正确性是如此困难,以及查找错误如此费时,因此从一开始开发应用程序就要在心中牢记线程的安全性,这 ...
大家都知道java构造 的使用方法吧, 可能大家都用它来进行对象的初始化。 就像下面这样一个例子。   public   class  Test ... {      public   static   void  main(String [] args)      ... {      & ...
不变对象具备许多能更方便地使用他们的特性,包括不严格的同步需求和不必考虑数据讹误就能自由地共享和高速缓存对象引用。尽管不变性可能未必对于任何类都 有意义,但大多数程式中至少有一些类将受益于不可变。在本月的 Java 理论和实践中,Brian Goetz 说明了不变性的一些长处和构造不变类的一些准则。请在附带的论坛中和作者和其他读者分享您关于本文的心得。(也能够单击文章顶部或底部的“讨论”来访问论 坛。) 不变对象是指在实例化后其外部可见状态无法更改的对象。Java 类库中的 String、Integer 和 BigDecimal 类就是不变对象的示例 &mda ...
同步的基本规则:只要读取可能由其他线程写入的变量,或者写入随后由其他线程读取的变量,就必须进行同步。很容易“忘记”这个规则,特别是在读取时。
  多线程 是一种机制,它允许在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间相互独立。多线程和传统的单线程在程序设计上最大的区别在于,由于各个线程的控制流彼此独立,使得各个线程之间的代码 是乱序执行的。任何线程都有四种状态:产生(New),可执行(Runnable),阻塞(Blocked),死亡(Dead)。 1.Java 的多线程 在 Java中实现多线程有两种方法:第一种方法是继承Thread 类, 覆盖方法run()。即创建Thread类的子类并重写run()方法,加入线程所要执行的代码即可。种方法简单明了,但是它有一个很大的缺点,就是一个 ...
     所 谓不可变类,是指当创建了这个类的实例后,就不允许修改它的属性值。在JDK的基本类库中,所有基本类型的包装类,如Integer和Long类,都是不 可变类,java.lang.String也是不可变类。以下代码创建了一个String对象和Integer对象,它们的值分别为“Hello”和 10,在程序代码中无法再改变这两个对象的值,因为Integer和String类没有提供修改其属性值的接口。 String s=new String("Hello"); I ...
1、UP项目将工作和迭代分为四个阶段: 初始,大体上的构想,业务案例、范围和模糊评估。 细化,已精化的构想、核心架构的迭代实现,高风险的解决、确定大多数需求和范围以及进行更为实际的评估。 构造,对遗留下来的风险较低和比较简单的元素进行迭代实现,准备部署。 移交,进行beta测试和部署。 2、初始阶段不是需求阶段,而是研究可行性的阶段,在此阶段要进行充分的调查以确定继续或种植项目。   3、细化阶段也不是需求或设计阶段,而是迭代地实现核心架构并解决高风险问题的阶段。
1、UP倡导的核心思想是:短时间定量迭代、进化和可适应开发。   2、在早期迭代中解决高风险和高价值的问题。   3、不断让用户参与评估、反馈和需求。   4、在早期迭代中建立内聚的核心架构。   5、不断地验证质量:提早、经常和实际地测试。   6、在适当的地方使用用例。   7、进行一些可视化建模(使用UML)。   8、认证管理需求。   9、实行变更请求和配置管理。
2008-05-26

敏捷UP

关键字: up 统一过程
1、推荐使用UP活动和制品的简集。记住,所有UP制品都是可选的,除非他们能够增加价值,否则避免创建这些制品。应该致力于早期的编程,而非构建文档。   2、UP是迭代的和不断进化的,所以在实现前的需求和设计都是不完整的。它们是在一系列迭代中,基于反馈而产生的。   3、以敏捷建模实践应用UML。   4、对于整个项目不应该有详细的计划。应该制定估计结束日期和主要里程碑的高阶计划(称为阶段计划),但是不要对这些里程碑详细定义细粒度的步骤。只能预先对一个迭代制定更为详细的计划(称为迭代计划)。详细计划是由一次次迭代的调整而完成的。
2008-05-26

final

final在Java中并不常用,然而它却为我们提供了诸如在C语言中定义常量的功能,不仅如此,final还可以让你控制你的成员、方法或者是一个类是 否可被覆写或继承等功能,这些特点使final在Java中拥有了一个不可或缺的地位,也是学习Java时必须要知道和掌握的关键字之一。 final成员 当 你在类中定义变量时,在其前面加上final关键字,那便是说,这个变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于 对象变量来说其引用不可再变。其初始化可以在两个地方,一是其定义处,也就是说在final变量定义时直接给其赋值,二是在构造函数中。这两个地方只能 ...
2008-05-26

利于ThreadLocal管理Hibernate Session

关键字: threadlocal hibernate session
      在利用Hibernate开发DAO模块时,我们和Session打的交道最多,所以如何合理的管理Session,避免Session的频繁创建和销 毁,对于提高系统的性能来说是非常重要的,以往是通过eclipse的插件来自动完成这些代码的,当然效果是不错的,但是总是觉得不爽(没有读懂那些冗长 的代码),所以现在打算自己实现Session管理的代码。我们知道Session是由SessionFactory负责创建的,而 SessionFactory的实现是线程安全的,多个并发的线程可以同时访问一个SessionFactory并从 ...
2008-05-26

ThreadLocal的几种误区

关键字: threadlocal
ThreadLocal的几种误区  最近由于需要用到ThreadLocal,在网上搜索了一些相关资料,发现对ThreadLocal经常会有下面几种误解  一、ThreadLocal是java线程的一个实现       ThreadLocal的确是和java线程有关,不过它并不是java线程的一个实现,它只是用来维护本地变量。针对每个线程,提供自己的变量版本,主要是为了避免线程冲突,每个线程维护自己的版本。彼此独立,修改不会影响到对方。  二、ThreadLocal是相对于每个s ...
2008-05-26

Java中ThreadLocal的设计与使用

关键字: threadlocal 多线程
    早在Java 1.2推出之时,Java平台中就引入了一个新的支持:java.lang.ThreadLocal,给我们在编写多线程程序时提供了一种新的选择。使用 这个工具类可以很简洁地编写出优美的多线程程序,虽然ThreadLocal非常有用,但是似乎现在了解它、使用它的朋友还不多。    ThreadLocal是什么     ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是thread local variable(线程局部变量)。也许把它命名为ThreadL ...
线程封闭 新一篇: 线程安全 function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+e ...
设计模式之Visitor 板桥里人 http://www.jdon.com 2002/05/05(转载请保留) Visitor访问者模式定义 作用于某个对象群中各个对象的操作. 它可以使你在不改变这些对象本身的情况下,定义作用于这些对象的新操作. 在Java中,Visitor模式实际上是分离了collection结构中的元素和对这些元素进行操作的行为. 为何使用Visitor? Java的Collection(包括Vector和Hashtable)是我们最经常 ...
Java 理论和实践: 安全构造技术 在构造期间,不要让“this”引用逃脱 <!-- document.write('<tr valign="top"><td width="8"><img src="//www.ibm.com/i/c.gif" width="8" height= ...
2008-05-26

敏捷建模

关键字: 敏捷建模 uml
1、建模(构建UML草图...)的目的主要是为了理解,而非文档。也就是说,建模的真正行为能够并且是应该能够对理解问 题或解决方案空间提供更好的方式。从这个角度而言,实行“UML”(其真正含义是“实行OOA/D”)的目的并不是指设计者创建大量详细的UML图并递交 给编程者(这其实是非敏捷的和面向瀑布的思维方式),而是指为良好的OO设计快速探索可选的方案和途径。   2、采用敏捷建模并不是不进行任何建模。   3、建模和模型的目的主要用于理解和沟通,而非构建文档。   4、不要对所有或大多数软件设计建模或 ...
2008-05-26

如何进行迭代和进化式分析和设计

关键字: 迭代 进化式
1、编程前的分析和设计并非毫无价值。迭代和进化式分析和设计是中庸之道。   2、精化的、高质量的需求基于反馈和计划的。在进行了项目过程的20%时,完成需求的精化,UP中,这一阶段称之为细化阶段。   3、UP提倡“风险驱动”和“客户驱动”相结合的迭代计划。这意味着早期的迭代目标要能够识别和降低最高风险,并且能够构造客户最关心的可视化特性。   4、风险驱动迭代开发更为明确地包含了“以架构为中心”迭代开发的实践。意味着早期迭代主要致力于核心架构的构造、测试和稳定。为什么?因为没有稳定 ...
  一、引子   对于系统中一个已经完成的类层次结构,我们已经给它提供了满足需求的接口。但是面对新增加的需求,我们应该怎么做呢?如果这是为数不多的几次变动,而且你不用为了一个需求的调整而将整个类层次结构统统地修改一遍,那么直接在原有类层次结构上修改也许是个不错的主意。   但是往往我们遇到的却是:这样的需求变动也许会不停的发生;更重要的是需求的任何变动可能都要让你将整个类层次结构修改个底朝天……。这种类似的操作分布在不同的类里面,不是一个好现象,我们要对这个结构重构一下了。   那么,访问者模式也许是你很好的选择。   二、定义与结构 ...
1、重复的代码   首当其冲的是重复代码。如果在一个以上地点看到相同的程序结构,那么可以肯定,设法将其合二为一,程序会变得更好。 2、长函数   拥有短函数的对象会活的比较好、比较长。间接层所带来的全部利益-解释能力、共享能力、选择能力-都是由小型函数支持的。   应该积极分解函数,应该遵循这样一个原则:每当感觉需要以注释来说明什么的时候,我们就把需要说明的东西写到一个独立的函数中,并以其用途(而非实现手法)命名。   我们可以对一组或甚至短短一行代码做这件事,哪怕替换后的函数调用比函数本身还长,只要函数名称能够解释其用途,我们也该毫不犹豫 ...
2008-05-24

瀑布生命周期

关键字: 瀑布 迭代 进化
1、瀑布(或顺序)生命周期过程中,视图在编程之前详细定义所有或大部分需求。而且通常在编程之前创建出完整的设计或模型。同样试图在开始之前定义“可靠”的计划或时间表,但常常事与愿违。   2、瀑布模型与高失败率、低生产率、高缺陷率具有极大关系(与迭代项目相比)。   3、瀑布思维常常侵蚀迭代或UP项目。例如“让我们在开发编程之前编写所有用例”或“让我们在开始编程之前用UML完成更多详细的OO模型”。诸如这种不健康的瀑布思维错误地叠加在UP上的例子。   4、初始阶段进行大量的分析和建模 ...
2008-05-24

迭代、进化、敏捷1

关键字: 迭代 进化 敏捷 rup
1、相对于“瀑布”生命周期,迭代和进化式开发对部分系统及早地引入了编程和测试,并重复这一循环。这种方式通常 在还没有详细定义所有需求的情况下假设开发开始,同时使用反馈来明确和改进演化中的规格说明。 2、迭代开发中,我们依赖于短时快速的开发步骤、反馈和改写来不断明确需求和设计。相比之下,瀑布模型提倡在编程 之前就预先完成需求和设计。 3、一直依赖,瀑布模型总是和软件项目的高失败率具有极大关系。 4、UP(Unified Process)已称为一种流行的构造面向对象系统的迭代式软件开发过程。特别是RUP(Rational Unifi ...
2008-05-24

修改接口

关键字: 接口 异常
1、接口修改了,什么事情都可能发生。   2、当需要修改的接口被那些“找不到,即使找到也无法修改”的代码使用时,接口的修改才会成为问题。这种情况下,我们会说,这个接口是“已发布接口”。   3、如果重构手法改变了“已发布接口”,你必须同时维护新旧两个接口,知道所有用户都有时间对这个变化做出反应,这不太困难。请尽量这么做:让旧接口调用新接口。当你修改函数名称时,请留下旧函数,让旧函数调用新函数。千万不要拷贝函数实现代码,那样会让你陷入“重复代码”的泥沼。   ...
2008-05-24

重构笔记1

关键字: 重构
1、好代码的两个重要标志:易读、易改。   2、重构的定义:在不改变代码的外在行为的前提下,对代码做出修改,以改进程序的内部结构。   3、当你发现自己需要为一个程序添加一个特性,而代码的结构使得你不能很方便的这么做,那么先重构那个程序,使得特性的添加比较容易进行,然后再添加特性。   4、设计不良的程序,往往需要更多的代码,因为在不同的地方存在使用完全相同的语句在做同样的事情。   5、重构可以改进设计,而改进设计的一个重要方向,就是消除重复代码。代码数量的减少不会使系统运行更快,然后代码数量的减少使得未来可能的修改变得容易的多。 & ...
Java多核线程笔记-volatile的原理与技巧 volatile, 用更低的代价替代同步 为什么 使用volatile比同步代价更低? 同步的代价, 主要由其覆盖范围决定, 如果可以降低同步的覆盖范围, 则可以大幅提升程序性能.  而volatile的覆盖范围仅仅变量级别的. 因此它的同步代价很低. volatile原理是什么? volatile的语义, 其实是告诉处理器, 不要将我放入工作内存, 请直接在主存操作我.(工作内存详见java内存模型) 因此, 当多核或多线程在访问该变量时, ...
JAVA的JVM的内存可分为3个区:堆(heap)、栈(stack)和方法区(method) 堆区: 1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令) 2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放数据 栈区: 1.每个线程包含一个栈区,栈中只保存原始类型数据和对象和对象引用(不是对象),对象都存放在堆区中 2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。 3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。 方法区: 1.又叫静态 ...
1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。    2. 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共 享,详见第3点。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要 在运行时动态分配内存,存取速度较慢。   3. Java中的数据类型有两种。   一种是基本类型(primitive t ...
jokermanager
搜索本博客
最近加入圈子
存档
最新评论