并发与高并发(十二)-线程安全策略

前言

主体概要

  • 不可变对象
  • 线程封闭
  • 线程不安全类与写法
  • 同步容器
  • 并发容器及安全共享策略总结 

主体内容

一、不可变对象

概念:不可变对象是指一个对象的状态在对象被创建之后就不再变化。

不可变对象需要满足的三个条件:

  • 对象创建以后其状态就不能修改
  • 对象所有域都是final类型
  • 对象是正确创建的(对象在创建期间,this引用没有溢出)

1.这里不得不提到Java中的一个关键字final,首先复习一下final关键字的作用。

当final修饰类:这个类不能被继承。

当final修饰方法:(1)锁定方法不被继承类修改(2)效率

当final修饰变量:基本数据类型变量不可变,引用类型变量不可指向新的地址

2.接下来,通过代码的形式继续复习一下final。

public class FinalOverView {
    private final static Integer a= 1;
    private final static String b ="2";
    private final static Map<Integer,Integer> map = Maps.newHashMap();
    
    static{
        map.put(1, 2);
        map.put(3, 4);
        map.put(5, 6);
    }
    
    public static void main(String[] args){
        
    }
}

PS:这里需要导入一个依赖包,不然Maps.newHashMap()方法无法使用。

<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>23.0</version>
    </dependency>

如上代码所示,如果我在main方法中加入以下代码,则是不被允许的,编译报错。

但是,当我们在main方法中重新将map的value值进行变动,却是被允许的。

public static void main(String[] args){
        map.put(1, 3);
        log.info("{}",map.get(1));
    }

结果:

21:51:08.730 [main] INFO com.controller.immutable.FinalOverView - 3

既然如此,那么就会有线程安全方面的问题。

好了,final部分简单的复习完了,接下来处理一下刚刚map的线程不安全问题。

这里先介绍两种方法:

  • Collections.unmodifiableXXX:Collection、List、Set、Map...
  • Guava:ImmutavleXXX:Collection、List、Set、Map...

如果采用Collections.unmodifiableMap()方法,下面再重新map.put()则运行就会抛出异常。

@Slf4j
public class Unmodifiable {
    
    private static Map<Integer,Integer> map = Maps.newHashMap();
    
    static{
        map.put(1, 2);
        map.put(3, 4);
        map.put(5, 6);
        map = Collections.unmodifiableMap(map);
    }
    
    public static void main(String[] args){
        map.put(1, 3);
        log.info("{}",map.get(1));
    }
}

结果:

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.Collections$UnmodifiableMap.put(Unknown Source)
    at com.controller.immutable.Unmodifiable.main(Unmodifiable.java:22)

此时就能保证它的线程安全了。

演示完unmodifiableMap,接下来看一下Immutablexxx。

    private final static ImmutableList<Integer> list = ImmutableList.of(1,2,3);
    
    private final static ImmutableSet set = ImmutableSet.copyOf(list);
    
    public static void main(String[] args){
        list.add(4);
    }

结果:

Exception in thread "main" java.lang.UnsupportedOperationException
    at com.google.common.collect.ImmutableCollection.add(ImmutableCollection.java:221)
    at com.controller.immutable.ImmuableList.main(ImmuableList.java:12)

如果main方法中换成set.add(4)呢?结果如下:

Exception in thread "main" java.lang.UnsupportedOperationException
    at com.google.common.collect.ImmutableCollection.add(ImmutableCollection.java:221)
    at com.controller.immutable.ImmuableList.main(ImmuableList.java:13)

可见,都会抛出相应的异常。

与前面的List,Set不同的是,Map定义稍有不同。

以下是两种方法:

private final static ImmutableMap<Integer,Integer> map = ImmutableMap.of(1,2,3,4);//key value key value
    
private final static ImmutableMap<Integer,Integer> map2 = ImmutableMap.<Integer,Integer>builder().put(1,2).put(3,4).build();

猜你喜欢

转载自www.cnblogs.com/jmy520/p/12081449.html