浏览 1149 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2012-12-25
不可变对象(Immutable Objects)
如果一个对象的状态在其创建之后不能被改变,那我们就说它是不可变对象。在多线程编程中,最大程度地使用不可变对象可以实现简单又可靠的代码。 不可变对象在并发应用中特别有用。因为它们不会改变状态,它们在遇到线程干扰和不一致访问时也不会出错(译注:因为每个线程在试图改变一个对象时,实际上是得到了该对象在最新状态下的拷贝,例如String就是不可变对象)。 程序员经常不愿使用不可变对象,因为他们担心拷贝对象会降低性能。实际上,创建对象的资源耗费常被高估(overestimated),实际上这样的资源耗费完全可以被不可变对象提高的效率抵消掉。使用不可变对象可以降低因垃圾回收产生的对象管理开支,消除为保护可变对象不被污染的额外代码。 下面几个小节里将创建一个状态可变的类,然后演化成一个状态不可变的类。以此描述转换要遵守的规则以及不可变对象相对于可变对象的优势。 一个同步类的例子 SychronizedRGB类定义了表示颜色对象的集合。每一个对象代表一种颜色,每一种颜色用三个表示基本色的整数和一个描述颜色名称的字符串表示。 public class SynchronizedRGB { // Values must be between 0 and 255. private int red; private int green; private int blue; private String name; private void check(int red, int green, int blue) { if (red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) { throw new IllegalArgumentException(); } } public SynchronizedRGB(int red, int green, int blue, String name) { check(red, green, blue); this.red = red; this.green = green; this.blue = blue; this.name = name; } public void set(int red, int green, int blue, String name) { check(red, green, blue); synchronized (this) { this.red = red; this.green = green; this.blue = blue; this.name = name; } } public synchronized int getRGB() { return ((red << 16) | (green << 8) | blue); } public synchronized String getName() { return name; } public synchronized void invert() { red = 255 - red; green = 255 - green; blue = 255 - blue; name = "Inverse of " + name; } } SynchronizedRGB必须谨慎使用来避免读写不一致。譬如,一个线程这样执行时: SynchronizedRGB color = new SynchronizedRGB(0, 0, 0, "Pitch Black"); ... int myColorInt = color.getRGB(); //Statement 1 String myColorName = color.getName(); //Statement 2 另一个线程在Statement 1之后,Statement 2之前调用color.set。那么myColorInt的值就与对应的myColorName不一致。为了避免这样的结果,两条语句必须绑定执行: synchronized (color) { int myColorInt = color.getRGB(); String myColorName = color.getName(); } 这种不一致只会在可变对象上发生 ——对于不可变版本的SynchronizedRGB不会有问题。 定义不可变对象的一种策略 下面的规则说明了创建不可变对象的一种简单策略。并不是所有的不可变类都要遵循下面的规则,也并不是说这些类的创建者都是糊涂蛋——他们有充分的理由相信这些类的实例在创建之后不会改变状态。然而,这样的策略需要复杂的分析,初学者慎用。
将策略应用到SynchronizedRGB需要一下几步:
经过一些改变,我们得到了ImmutableRGB: final public class ImmutableRGB { // Values must be between 0 and 255. final private int red; final private int green; final private int blue; final private String name; private void check(int red, int green, int blue) { if (red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) { throw new IllegalArgumentException(); } } public ImmutableRGB(int red, int green, int blue, String name) { check(red, green, blue); this.red = red; this.green = green; this.blue = blue; this.name = name; } public int getRGB() { return ((red << 16) | (green << 8) | blue); } public String getName() { return name; } public ImmutableRGB invert() { return new ImmutableRGB(255 - red, 255 - green, 255 - blue, "Inverse of " + name); } } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |