乐趣区

关于多线程:Java线程安全策略

线程安全策略

创立后状态不能被批改的对象叫做不可变对象. 不可变的对象天生就是线程平安的. 不可变对象的常量 (变量) 是在构造函数中创立的, 既然它们的状态永远无奈被扭转, 那么它们永远就是线程平安的。

不可变对象须要满足的条件

  • 对象创立当前其状态就不能批改。
  • 对象的所有域都是 fina 类型。
  • 对象是正确创立的(在对象创立期间,this 援用没有逸出)

并发编程实际中,this 援用逃逸(”this”escape)是指对象还没有结构实现,它的 this 援用就被公布进来了

final

final 关键字: 类, 办法, 变量。

  • 润饰类

不能被继承,final 类中的成员属性能够依据须要设置成 final, 然而final 类中所有的成员办法都被隐式的指定为final, 个别不倡议将类设置成final.

  • 润饰办法

锁定办法不能被继承类批改

  • 润饰变量

根本数据类型变量, 初始化后就不能被批改。援用类型变量, 在初始化后就不能指向别的援用。

// 线程不平安

package com.rumenz.task.single;

import com.google.common.collect.Maps;
import java.util.Map;

public class ImmutableExample1 {

    private final static Integer a=1;
    private final static Integer b=2;

    // 指向的援用不能被批改, 然而 map 外面的值能够批改
    private final static Map<Integer,Integer> map= Maps.newHashMap();


    static {map.put(1, 1);
    }

    public static void main(String[] args) {
       //a=10; 编译期报错
       //b=20; 编译期报错
       map.put(2, 2); // 线程不平安
    }
}

Collections

java提供 Collections 工具类, 在类中提供了多种不容许批改的办法。

Collections.unmodifiableXXX:Collection、List、Set、Map…

// 线程平安
package com.rumenz.task.single;

import com.google.common.collect.Maps;

import java.util.Collections;
import java.util.Map;


public class ImmutableExample1 {

    private final static Integer a=1;
    private final static Integer b=2;

    // 指向的援用不能被批改, 然而 map 外面的值能够批改
    private  static Map<Integer,Integer> map= Maps.newHashMap();


    static {map.put(1, 1);
        // 解决后 map 是不能够被批改的
        map= Collections.unmodifiableMap(map);
    }

    public static void main(String[] args) {
       // 容许操作, 然而操作会报错
       map.put(2, 2);
    }
}


Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.Collections$UnmodifiableMap.put(Collections.java:1457)
    at com.rumenz.task.single.ImmutableExample1.main(ImmutableExample1.java:31)

Collections.unmodifiableMap源码

public class Collections {public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m) {return new UnmodifiableMap<>(m);
    }
    private static class UnmodifiableMap<K,V> implements Map<K,V>, Serializable {
        @Override
        public boolean remove(Object key, Object value) {throw new UnsupportedOperationException();
        }

        @Override
        public boolean replace(K key, V oldValue, V newValue) {throw new UnsupportedOperationException();
        }
    }
}

Guava

谷歌的 Guava 中提供相似 Java 中的Collections

ImmutableXXX:Collection、List、Set、Map…

<dependency>
   <groupId>com.google.guava</groupId>
   <artifactId>guava</artifactId>
   <version>23.0</version>
</dependency>
// 线程平安

public class ImmutableExample3 {private final static ImmutableList<Integer> list = ImmutableList.of(1, 2, 3);
    
    private final static List<Integer> lists = ImmutableList.of(1, 2, 3);

    private final static ImmutableSet set = ImmutableSet.copyOf(list);

    private final static ImmutableMap<Integer, Integer> map = ImmutableMap.of(1, 2, 3, 4);

    private final static ImmutableMap<Integer, Integer> map2 = ImmutableMap.<Integer, Integer>builder()
            .put(1, 2).put(3, 4).put(5, 6).build();

    public static void main(String[] args) {System.out.println(map2.get(3));
    }
}

退出移动版