Java 理论与实践专栏是由经验丰富的 Java 开发人员 Brian Goetz 撰写的一个专栏月刊。本专栏旨在探索设计原则如何满足解决实际问题的需求这一难以捉摸的结合点。每个月我们都将探索设计模式、可靠软件设计的原则以及为什么“最佳实践”是最好的,同时也关注如何将它们应用于实际问题。

2008 年

应用 fork-join 框架,第 2 部分
2008 年 4 月
Java 7 中的 java.util.concurrent 包的新增功能之一是一个用于 fork-join 风格的并行分解的库。本文将介绍 ParallelArray 类,这个类简化了内存中数据结构上的并行排序和搜索操作。

2007 年

应用 fork-join 框架,第 1 部分
2007 年 12 月
Java 7 的 java.util.concurrent 包的新增功能之一是一个 fork-join 风格的并行分解框架。fork-join 概念提供了一种分解多个算法的自然机制,可以有效地应用硬件并行性。

正确使用 Volatile 变量
2007 年 7 月
Java 语言包含两种内在同步机制:同步块(或方法)和 volatile 变量。这两种机制的提出都是为了实现代码线程的安全性。其中 Volatile 变量的同步性较差(但有时它更简单并且开销更低),而且使用也更容易出错。本期 Brian Goetz 将介绍几种正确使用 volatile 变量的模式,并针对其适用性限制提出了一些建议。

闭包之争
2007 年 5 月
Java 语言是否应该引入像闭包这样的主流新特性,然而过多特性又会不会使得原本好端端的语言过于复杂?在本文中,Brian Goetz 回顾了相关概念,并详细介绍了两种相互竞争的闭包方案。

在 JDK 早期版本中使用 Java 5 的语言特性
2007 年 3 月
Java? 5 添加了许多强大的语言特性:泛型、枚举、注释、自动装箱和增强的 for 循环。但是,许多工作组仍然被绑定在 JDK 1.4 或以前的版本上,可能需要花些时间才能使用新版本。但是,这些开发人员仍然可以使用这些功能强大的语言特性,同时在 JVM 早期版本上部署。在这一期 Java 理论与实践 中,Brian Goetz 将演示如何在 JDK 早期版本中使用 Java 5 的语言特性。

2006 年

用 JMX 检测应用程序
2006 年 10 月
调试器和分析器可以提供对应用程序的行为的深入观察,但在出现严重问题之前,这些工具通常用不上。将监视挂钩(hook)构建到应用程序内,会使理解程序的执行变得更容易而且不会破坏调试器。既然 Java 管理扩展(JMX)已经构建进了 Java SE 平台,而且 jconsole 查看器提供了统一的监视 GUI,那么用 JMX 为应用程序提供一个窗口,要比以前更加容易而且更为有效。

平衡测试,第 3 部分
2006 年 9 月
在关于测试的最后这一期中,Brian Goetz 介绍另一种发现违犯设计规则之处的技术:方面。

平衡测试,第 2 部分
2006 年 9 月
在本期专栏中,专职 bug 清除专家 Brian Goetz 将详细说明构造和调优不平凡的 bug 模式检测器的过程。

平衡测试,第 1 部分
2006 年 7 月
2004 年 6 月,经验丰富的 Bug 清除专家 Brian Goetz 引进了 FindBugs 静态代码分析工具,即使在测试良好的软件中,该工具也可以检测 bug。本月他将重拾该主题,查看静态分析工具如何通过开发存在所有种类的 bug 的资源(而不是特定实例)来改进管理软件质量的方式。

处理 InterruptedException
2006 年 6 月
本月并发专家 Brian Goetz 将解释 InterruptedException 的含义,为什么抛出 InterruptedException,以及在捕捉到该异常时应该怎么做。

非阻塞算法简介
2006 年 5 月
Java 5.0 第一次让使用 Java 语言开发非阻塞算法成为可能,非阻塞算法属于并发算法,它们可以安全地派生它们的线程,不通过锁定派生,而是通过低级的原子性的硬件原生形式 ―― 例如比较和交换。本期并发性大师 Brian Goetz 演示了几种比较简单的非阻塞算法的工作方式。

良好的内务处理实践
2006 年 4 月
垃圾收集几乎是每位 Java 平台开发人员都喜爱的一个特性,它简化了开发,消除了潜在的代码错误。可是尽管垃圾收集通常可以让您无需进行资源管理,但有时候您还是必须自己进行一些内务处理。本期 Brian Goetz 讨论了垃圾收集的局限性,并介绍了您必须自己做内务处理的场景。

伪 typedef 反模式
2006 年 3 月
将泛型添加到 Java 语言中增加了类型系统的复杂性,提高了许多变量和方法声明的冗长程度。因为没有提供 “typedef” 工具来定义类型的简短名称,所以有些开发人员转而把扩展当作 “穷人的 typedef”,但是收到的决不是好的结果。本月 Java 专家 Brian Goetz 解释了这个 “反模式” 的限制。

用弱引用堵住内存泄漏
2006 年 1 月
虽然用 Java 语言编写的程序在理论上是不会出现“内存泄漏”的,但是有时对象在不再作为程序的逻辑状态的一部分之后仍然不被垃圾收集。本月, Brian Goetz 探讨了无意识的对象保留的常见原因,并展示了如何用弱引用堵住泄漏。

2005 年

Mustang 中的同步优化
2005 年 11 月
在上期中 Brian Goetz 研究了 Escape 分析,这是许多 JVM 在相当一段时间内已经放入日程表的一项优化,也是预计会在 Mustang (Java SE 6)发行版的 HotSpot 中出现的优化。这个月,Brian 将介绍一些为 Mustang 安排的同步优化。

再谈 Urban 性能传言
2005 年 10 月
Java 语言遭到许多性能方面的攻击。虽然有些攻击可能是名符其实的,但是看看公告板和新闻组上关于这一主题的贴子,可以发现,对于 Java 虚拟机(JVM)实际的工作方式存在许多误解。本月 Brian Goetz 驳斥了反复重复的有关 JVM 分配慢的传言。

用动态代理进行修饰
2005 年 9 月
动态代理工具是 java.lang.reflect 包的一部分,在 JDK 1.3 版本中添加到 JDK,它允许程序创建 代理对象。本文中,Brian Goetz 介绍了几个用于动态代理的应用程序。

做个好的(事件)侦听器
2005 年 8 月
观察者模式在 Swing 开发中很常见,在 GUI 应用程序以外的场景中,它对于消除组件的耦合性也非常有用。但是,仍然存在一些侦听器登记和调用方面的常见缺陷。这一期中,Java 专家 Brian Goetz 就如何做一个好的侦听器,以及如何对您的侦听器友好,提供了一些感觉很好的建议。

在没有数据库的情况下进行数据库查询
2005 年 6 月
本月 Brian Goetz 将演示如何将 SQL 或者 XQuery 这样的数据操纵应用于非持久存储的数据。

用 XQuery 进行屏幕搜集
2005 年 4 月
XQuery 是用来从 XML 文档中提取信息的 W3C 标准,目前包括 14 个工作草案。虽然 XQuery 主要集中于查找大型半结构化文档数据,但是令人惊讶的是 XQuery 对于一些更平凡的应用也非常有效。本月 Brian Goetz 将介绍如何有效地把 XQuery 用作 HTML 的屏幕搜集引擎。

一个有缺陷的微基准的剖析
2005 年 3 月
虽然有时候性能在一个软件项目中是最重要的需求,但在大多数情况下,需要在性能需求与其他需求之间进行平衡,例如功能性、可靠性、可维护性、可扩展性、投入市场的时间以及其他业务和工程上的考虑。本月专栏作家 Brian Goetz 将探讨为什么度量 Java 语言结构体的性能比看上去要难得多。

2004 年

动态编译与性能测量
2004 年 12 月
为动态编译的语言(例如 Java)编写和解释性能评测,要比为静态编译的语言(例如 C 或 C++)编写困难得多。本期 Brian Goetz 介绍了动态编译使性能测试复杂的一些原因。

流行的原子
2004 年 12 月
在 JDK 5.0 之前,如果不使用本机代码,就不能用 Java 语言编写无等待、无锁定的算法。在 java.util.concurrent 中添加原子变量类之后,这种情况发生了变化。请跟随并行专家 Brian Goetz 一起,了解这些新类如何使用 Java 语言开发高度可伸缩的无阻塞算法。

JDK 5.0 中更灵活、更具可伸缩性的锁定机制
2004 年 11 月
JDK 5.0 为开发人员开发高性能的并发应用程序提供了一些很有效的新选择。例如,java.util.concurrent.lock 中的类 ReentrantLock 被作为 Java 语言中 synchronized 功能的替代,它具有相同的内存语义、相同的锁定,但在争用条件下却有更好的性能,此外,它还有 synchronized 没有提供的其他特性。这是否意味着我们应当忘记 synchronized,转而只用 ReentrantLock 呢?并发性专家 Brian Goetz 刚从他的夏季休假中返回,他将为我们提供答案。

Web 层的状态复制
2004 年 8 月
本月,Brian Goetz 分析了状态复制的一些选项以及如何最有效地使用 HttpSession 以提供好的伸缩性和性能。

消除 bug
2004 年 7 月
本月,Brian Goetz 以 Chris Grandstaff 在前面发表的 FindBugs,第 1 部分: 提高代码质量 为基础,向您展示了这个静态分析工具如何帮助分析代码,以使其符合本栏目前面的文章中讨论过的设计原理。

关于异常的争论
2004 年 6 月
关于在 Java 语言中使用异常的大多数建议都认为,在确信异常可以被捕获的任何情况下,应该优先使用检查型异常。最近,几位著名的作者已经开始认为非检查型异常在优秀的 Java 类设计中有着比以前所认为的更为重要的地位。在本文中,Brian Goetz 考察了关于使用非检查型异常的优缺点。

让 J2EE 脱离容器
2004 年 5 月
大多数项目不是属于 J2EE 应用程序就是属于 J2SE 应用程序。不过,有一些 J2EE 技术可以存在于 J2EE 容器之外,并且有些 J2SE 应用程序可以对它们加以利用。本月,Brian Goetz 分析如何在 J2SE 应用程序中使用某些 J2EE 服务。

修复 Java 内存模型,第 2 部分
2004 年 4 月
这个月,Brian Goetz 介绍在新 JMM 中 volatile 和 final 的语义是如何变化的,这些改变使它们的语义符合大多数开发人员的直觉。其中一些改变已经在 JDK 1.4 中出现了,另一些改变则要等到 JDK 1.5。

修复 Java 内存模型,第 1 部分
2004 年 3 月
Brian Goetz 展示了如何加强 volatile 和 final 的语义,以修复 JMM。这些更改有些已经集成在 JDK 1.4 中;而另一些将会包含在 JDK 1.5 中。

2003 年

JVM 1.4.1 中的垃圾收集
2003 年 12 月
本文 Brian Goetz 将进一步探讨 JVM 1.4.1 是如何实际处理垃圾收集的,包括一些针对多处理器系统的新垃圾收集选项。

垃圾收集简史
2003 年 12 月
在本篇文章中,Brian Goetz 描述了垃圾收集最常用的技术。在以后的几个月,他将分析 1.4 JVM 所使用的垃圾收集策略、不同垃圾收集策略对性能的影响和如何才能(以及如何不能)帮助垃圾收集器取得更好的性能。

描绘线程安全性
2003 年 11 月
并发专家 Brian Goetz 将 Hashtable 和 Vector 类描述为“有条件线程安全的”。一个类难道不是线程安全就是线程不安全的吗?不幸的是,线程安全并不是一个非真即假的命题,它的定义出人意料的困难。但是,正如 Brian 在本文中解释的,尽量在 Javadoc 中对类的线程安全性进行归类是非常重要的。

构建一个更好的 HashMap
2003 年 9 月
ConcurrentHashMap 是 Doug Lea 的 util.concurrent 包的一部分,它提供比 Hashtable 或者 synchronizedMap 更高程度的并发性。本文 Brian Goetz 仔细分析了 ConcurrentHashMap 的代码,并探讨 Doug Lea 是如何在不损失线程安全的情况下取得这么骄人成绩的。

并发集合类
2003 年 9 月
Doug Lea 的 util.concurrent 包除了包含许多其他有用的并发构造块之外,还包含了一些主要集合类型 List 和 Map 的高性能的、线程安全的实现。本月 Brian Goetz 向您展示了用 ConcurrentHashMap 替换 Hashtable 或 synchronizedMap,将使并发程序获益多少。

它是谁的对象?
2003 年 9 月
尽管垃圾收集意味着 Java 开发者不必太多地担心内存 泄漏,有时我们仍然需要担心对象所有权,以防止数据争用(data races)和不必要的副作用。本文指出了一些这样的情况,即 Java 开发者必须注意对象所有权。

哈希
2003 年 8 月
每个 Java 对象都有 hashCode() 和 equals() 方法。许多类覆盖这些方法的缺省实现,以在对象实例之间提供更深层次的语义可比性。本文向您介绍创建有效和准确定义 hashCode() 和 equals() 的 Java 类时应遵循的规则和指南。

性能管理 ― 您有规划吗?
2003 年 6 月
在这一部分的 Java 理论与实践中,Brian Goetz 将讨论在项目中使用 Java 语言时遇到的一些最常见的性能错误。

变还是不变?
2003 年 5 月
不变对象具有许多能更方便地使用它们的特性,包括不严格的同步需求和不必考虑数据讹误就能自由地共享和高速缓存对象引用。本文说明了不变性的一些长处和构造不变类的一些准则。

并发在一定程度上使一切变得简单
2003 年 4 月
本文 Brian Goetz 将介绍 Doug Lea 的 util.concurrent 包,这是一个高质量的、广泛使用的、并发实用程序的开放源码包。

您的小数点到哪里去了?
2003 年 4 月
在本月的 Java 理论和实践中,Brian Goetz 探讨了在 Java 程序中使用非整数类型时一些常碰到的陷阱和“gotcha”。

2002 年

嗨,我的线程到哪里去了?
2002 年 12 月
如果您不小心,线程可能会在没有(堆栈)跟踪的情况下从服务器应用程序中消失。在本文中,线程问题专家 Brian Goetz 提供了用于预防和检测线程“擅离职守”的技术。

线程池与工作队列
2002 年 10 月
几乎在每个服务器应用程序中都会出现线程池和工作队列问题。本文中,Brian Goetz 探讨了线程池的动机、一些基本实现和调优技术以及一些要避免的常见危险。

理解 JTS ― 平衡安全性和性能
2002 年 5 月
本文 Brian 讨论了 J2EE 提供的用来管理事务划分和隔离的工具和一些高效率地使用这些工具的指导。

理解 JTS ― 幕后魔术
2002 年 4 月
在这一部分,我们将探讨如何将 J2EE 应用程序构建到事务中,以及 JTS 和 J2EE 容器如何设法使事务服务(包括事务划分、资源征用和事务传播)对组件程序员来说几乎是不可见的。

应该在下一个企业应用程序中使用 JMS 吗?
2002 年 2 月
在本文中,Brian 概述了在 Java 应用程序中使用消息排队的一些好处,并探讨了能够从 MQ 技术中获益最大的问题类型。

专栏作者

Brian Goetz 作为专业的软件开发人员已经有 20 年了。他是 Sun Microsystems 的高级工程师,并且效力于多个 JCP 专家组。Brian 的新书 Java Concurrency In Practice 在 2006 年 5 月由 Addison-Wesley 出版。请参阅 Brian 在流行的业界出版物上 已发表和即将发表的文章