• JAVA-不可变对象


    如果一个对象的状态在构造后不能改变,则该对象被认为是不可变的。例如 String。

    不可变对象在并发应用程序中特别有用。由于它们不能改变状态,因此它们不会被线程干扰破坏或在不一致状态下被观察到。

    定义一个普通同步类(可变对象)

    package com.example.Immutable;
    
    public class SynchronizedRGB {
    
        // 值必须介于0到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;
        }
    }
    View Code

    假设一个线程执行以下代码:

    SynchronizedRGB color = new SynchronizedRGB(0, 0, 0, "Pitch Black");
    ...
    int myColorInt = color.getRGB(); //Statement 1
    String myColorName = color.getName(); //Statement 2

    如果另一个线程 color.set() 在语句1之后但在语句2之前调用,则 myColorInt 将与 myColorName 不匹配 。为了避免这种结果,必须将两个语句绑定在一起:

    synchronized(color){ 
        int myColorInt = color.getRGB(); 
        String myColorName = color.getName(); 
    }

    这种不一致性只适用于可变对象。

    定义一个同步类(不可变对象)

    以下规则定义了用于创建不可变对象的简单策略。但并非所有“不可变”的类都遵循这些规则:

    1.不要提供属性的 setter 方法
    2.所有字段用 final 和 private 修饰
    3.不允许子类重写方法。最简单的方法是将类声明为 final。更复杂的方法是 private 在工厂方法中构造构造函数和构造实例
    4.如果实例字段包含对可变对象的引用,则不允许更改这些对象

    package com.example.Immutable;
    
    
    final public class ImmutableRGB {
    
        // 值必须介于0到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);
        }
    }
    View Code

    只有一个线程引用一个对象时,则该对象本身就是不可变的。因此,不需要防止改变的保护措施。


    https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html

  • 相关阅读:
    java JDBC (一)
    java 线程(七)等待与唤醒
    java 线程(六)死锁
    java 线程(五)线程安全 Lock接口
    java 线程(四)线程安全 同步方法
    查询计算机启动了多长时间的工具
    查询计算机启动了多长时间的工具
    百度同步盘无法登陆,报错155010,对策
    百度同步盘无法登陆,报错155010,对策
    锁屏工具,解决三星S7迷你锁屏后不能通过指纹解锁的问题
  • 原文地址:https://www.cnblogs.com/jhxxb/p/10523440.html
Copyright © 2020-2023  润新知