`
leichenlei
  • 浏览: 127829 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java并发(六、不可变对象)

    博客分类:
  • java
 
阅读更多

如果一个对象在构造之后不可改变,那么这个对象就是不可变对象。不可变对象被广泛认同的作用是建立简单、可靠代码的万全之策。

    不可变对象在并发应用程序中特别有用,因为他们不能被修改,他们不能发生线程冲突,或者发生不一致状态的读取。

    程序员经常不心甘情愿的使用不可变对象,因为他们不能修改这个对象,只能new一个对象。创建对象的开销一般是被评估过高的,可以和不可能变对象相关的效率问题抵消。包括,垃圾回收的开销和the elimination of code needed to protect mutable objects from corruption

    下面给出一个可变对象的类,从这个例子引导出不可变对象。这样可以对比出不可变对象的优势。

(一)           同步类的例子

SynchronizedRGB,是一个代表颜色的例子。每个对象的三个整数分别代表一个原色,然后一个string代表颜色名字。

 

 

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

如果另一个线程在statement1statement2之间调用coler.setmyColerIntmyColorName将不一致。为了避免这情况发生,两个语句必须绑定在一起:

synchronized (color) {

    int myColorInt = color.getRGB();

    String myColorName = color.getName();

}

这种情况只可能发生在可变对象,对于不可变对象版本的SynchronizedRGB这不是一个问题。

 

(二)           定义不可变对象的策略

接下来的规则定义了创建不可变对象的简单策略。并非所有的“不可改变的”类要遵循这些规则。这并不是说这些类的创建者是草率的——他们有很好的理由相信他们创建的类构造之后不会被改变。但是这要做复杂的分析,不适合初学者。

1,不要提供“setter”方法——那些修改域或者域关联的对象的方法。

2,让所有域都是finalprivate

3,不允许子类覆盖方法。最简单的方法是把class定义成final。更复杂的方法是把构造方法定义成private,然后通过工程方法构建实例。

4,如果对象的域引用了可变对象,不允许这些对象改变:?不提供修改这些对象的方法。

?不要共享可变对象的引用。不要通过构造方法存储可变对象的引用;如果有必要,创建对象副本,存储副本的引用。同样,避免在方法中返回原对象,而是创建你的内部可变对象的副本。

按照以下步骤给SynchronizedRGB添加这个策略:

1class有两个setter方法。第一个set方法,任意转换对象,在不可变版本里去掉。第二个invert方法,用创建一个新对象代替修改这个对象。

2,所有的域是privatefinal

3class被声明成final

4,只有一个域引用对象,这个对象是他自己。因此,不用考虑被包含的可变对象的改变。

做了这些,我们得到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);

     }

}

分享到:
评论

相关推荐

    Java并发编程规则:不可变对象永远是线程安全的.docx

    Java并发编程规则:不可变对象永远是线程安全的 在Java并发编程中,了解不可变对象的概念对于编写线程安全的代码至关重要。不可变对象是指创建后状态不能被修改的对象,这类对象天生就是线程安全的。它们的常量...

    Java中不可变对象的构建与应用:深入指南

    在Java编程中,不可变对象是指一旦创建后其状态不能被修改的对象。这种对象模式在多线程环境和频繁对象创建的场景下,提供了线程安全保证,减少了内存开销,并提高了代码的可维护性。本文将详细介绍如何在Java中创建...

    java并发编程2

    - 使用并发工具而非手工同步,如可能的话,优先选择不可变对象。 7. **Java内存模型** - **JMM(Java Memory Model)** 规定了线程如何访问和修改共享变量,以及对这些操作的排序规则,以保证多线程环境下的正确...

    java并发编程实战(英文版)

    - **不可变对象**:介绍如何设计不可变对象以提高代码的安全性和效率。 - **锁分离**:讲解锁分离技术,以及如何通过减少锁的竞争来提高程序性能。 - **无锁编程**:探讨无锁编程的基本原理和技术细节,包括使用原子...

    Java并发编程实战

    3.4.2 示例:使用Volatile类型来发布不可变对象 3.5 安全发布 3.5.1 不正确的发布:正确的对象被破坏 3.5.2 不可变对象与初始化安全性 3.5.3 安全发布的常用模式 3.5.4 事实不可变对象 3.5.5 可变对象 3.5.6 ...

    Java 并发核心编程

    - **定义**: 不可变字段在对象创建后被设置一次且不可更改。 - **特性**: 创建结束时,若对象被安全发布,则所有线程都可以获取到final字段在构造过程中设置的值,即使没有`synchronized`关键字。 #### 三、保护...

    java并发编程内部分享PPT

    Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。这份“java并发编程内部分享PPT”显然是一个深入探讨这一主题的资料,旨在帮助开发者...

    Java并发编程实践高清pdf及源码

    4. **线程池**:`ExecutorService`是Java并发框架的核心,它管理一组可重用线程,有效地调度和执行任务。`ThreadPoolExecutor`是其最常见的实现,允许自定义线程池参数。 5. **并发工具类**:如`CountDownLatch`、`...

    [Java并发编程实践].(Java.Concurrency.in.Practice).Brian.Goetz.英文原版.pdf

    - **不可变对象**:创建不可变对象是一种简化并发编程的有效方式。书中解释了不可变对象的概念及其在Java中的实现方法。 - **原子变量**:原子变量提供了一种简单的方式来更新基本类型的值,而无需显式同步。书中...

    java 并发编程实践

    - 使用不可变对象。 - 避免过度同步。 - 优先使用并发工具类而不是自建同步机制。 - 对于长时间运行的任务,考虑使用线程池。 以上内容涵盖了Java并发编程的多个关键点,从基础知识到高级技巧,希望对你理解和...

    Java并发编程学习笔记

    - 不可变对象(Immutable Objects):一旦创建就不能被修改的对象,天然线程安全。 学习Java并发编程,重点在于理解线程如何协同工作,以及如何确保并发执行的正确性和高效性。通过深入掌握Java并发API,可以为大型...

    java并发编程

    Java并发编程是Java开发者必须掌握的关键技能之一,它涉及到如何在多线程环境中高效、安全地执行程序。并发编程能够充分利用多核处理器的计算能力,提高应用程序的响应速度和整体性能。《Java编程并发实战》这本书是...

    java并发实战中文文档

    3. **锁**:Java并发库中的`java.util.concurrent.locks`包提供了更高级的锁机制,如可重入锁(`ReentrantLock`)、读写锁(`ReadWriteLock`)和条件变量(`Condition`),这些工具允许更灵活的控制并发访问。 4. **并发...

    Java并发编程设计原则和模式

    本资料“Java并发编程设计原则和模式”深入探讨了如何在Java环境中有效地进行并发处理,以充分利用系统资源并避免潜在的并发问题。 一、并发编程基础 并发是指两个或多个操作在同一时间段内执行,但并不意味着这些...

    JAVA并发编程实践 中文 高清 带书签 完整版 Doug Lea .pdf

    - **不可变对象**:一旦被创建就无法改变其状态的对象,在多线程环境下更加安全。 - **volatile变量**:用于确保变量的可见性和一定程度上的有序性。 #### 3.3 原子操作与原子类 - **原子操作**:在单个处理器上...

    Java 并发编程实战

    3.4.2 示例:使用Volatile类型来发布不可变对象 3.5 安全发布 3.5.1 不正确的发布:正确的对象被破坏 3.5.2 不可变对象与初始化安全性 3.5.3 安全发布的常用模式 3.5.4 事实不可变对象 3.5.5 可变对象 3.5.6 ...

    java并发实战编程 英文版

    书中会讲解什么是线程不安全,并给出避免线程安全问题的策略,如使用线程局部变量(ThreadLocal)和不可变对象。 3. **并发工具** Java并发库提供了丰富的工具类,如ExecutorService、Semaphore、CountDownLatch和...

    Java并发编程从入门到精通源码.rar

    Java并发编程是Java开发中的重要领域,特别是在大型分布式系统、多线程应用和服务器端程序设计中不可或缺。这个资源包“Java并发编程从入门到精通源码.rar”显然是为了帮助开发者深入理解并掌握这一关键技能。它包含...

Global site tag (gtag.js) - Google Analytics