美文网首页
线程安全策略(一)-不可变对象

线程安全策略(一)-不可变对象

作者: 墨平语凡 | 来源:发表于2018-06-03 09:26 被阅读0次

有一种对象只要发布了就是线程安全的——不可变对象

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

  • 对象创建以后其状态就不能修改
  • 对象所有域都是final类型 (这样只能对每个域赋值一次,通过构造器初始化所有成员,进行深度拷贝,在get方法中不直接返回对象本身,而是克隆对象并返回克隆)
  • 对象是正确创建的(在对象创建期间,this引用没有逸出)

final 关键字: 修饰 类、方法、变量

  • 修饰类:被修饰的类不能被继承
    final类中的成员变量可以根据需要设置为final,但是final类中的所有成员方法都会被隐式地指定为final方法. final修饰类的时候要谨慎原则,除非它以后不会被用来继承,或者出于安全考虑,否则尽量不要将类设置为final类)
  • 修饰方法:1. 锁定方法不被继承类修改 2. 效率 (一个类的private方法会隐式地被指定为final方法)
  • 修饰变量: 基本数据类型变量(数值一旦初始化之后就不能修改)、引用类型变量(初始化之后就不能让它指向另外的对象)
package io.haitaoc.concurrency.example.immutable;

import io.haitaoc.concurrency.annotation.NotThreadSafe;

import java.util.HashMap;
import java.util.Map;

@NotThreadSafe
public class ImmutableExample1 {

    private final static Integer a=1;
    private final static String b="2";
    private final static Map<Integer,Integer> map = new HashMap<>();

    static{
        map.put(1,2);
        map.put(3,4);
        map.put(5,6);
    }

    public static void main(String[] args) {
      //  a=2;      // 数值不能改变
      //  b="3";
      // map = new HashMap<>()    // 不能指向新的引用
        map.put(1,3);       // 里面的数值对可以改变
        map.entrySet().forEach(entry -> System.out.println("key:value = " + entry.getKey() + ":" + entry.getValue()));
    }

    private void test(final int a){
        // a = 1;          //  不允许修改传参为final修饰的变量
    }

}

其他方式定义不可变对象

Collections.unmodifiableXXX:List、Map...

package io.haitaoc.concurrency.example.immutable;

import io.haitaoc.concurrency.annotation.NotThreadSafe;
import io.haitaoc.concurrency.annotation.ThreadSafe;

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

@ThreadSafe
public class ImmutableExample2 {


    private  static Map<Integer,Integer> map = new HashMap<>();

    static{
        map.put(1,2);
        map.put(3,4);
        map.put(5,6);
        map = Collections.unmodifiableMap(map);
    }

    public static void main(String[] args) {
      //  a=2;      // 数值不能改变
      //  b="3";
      // map = new HashMap<>()    // 不能指向新的引用
        map.put(1,3);       // 里面的数值对可以改变
        map.entrySet().forEach(entry -> System.out.println("key:value = " + entry.getKey() + ":" + entry.getValue()));
    }

}

Guava第三方包中的, ImmutableXXX:List、Map...

package io.haitaoc.concurrency.example.immutable;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import io.haitaoc.concurrency.annotation.ThreadSafe;

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

@ThreadSafe
public class ImmutableExample3 {


    private final static ImmutableList list = 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> map = ImmutableMap.<Integer,Integer>builder().put(1,2).put(3,4).build();

    public static void main(String[] args) {
        // list.add(4);                // 抛出异常
        // set.add(4);
        map.put(1,4);

    }
}

相关文章

  • Java线程安全策略与多线程并发最佳实践

    线程安全策略 不可变对象 不可变对象(Immutable Objects)是指对象一旦被创建它的状态(对象的数据,...

  • 线程安全策略(一)-不可变对象

    有一种对象只要发布了就是线程安全的——不可变对象 不可变对象需要满足的条件 对象创建以后其状态就不能修改 对象所有...

  • Java高并发--线程安全策略

    Java高并发--线程安全策略 主要是学习慕课网实战视频《Java并发编程入门与高并发面试》的笔记 不可变对象 发...

  • Guava_集合篇

    关于不可变集合 当对象被不可信的库调用时,不可变形式是安全的; 不可变对象被多个线程调用时,不存在竞态条件问题 不...

  • 不变性

    不可变对象一定是线程安全的 那么什么是不可变对象呢? 当满足一下条件时,对象才是不可变的。 对象创建以后其状态就不...

  • 用不变对象解决竞态问题

    不可变对象 所有并发问题都是由于多个线程同时访问对象的某个可变属性引起的, 如果对象是不可变的, 那么所有的并发问...

  • 关于线程安全策略

    四个线程安全策略 1、线程限制: 一个被线程限制的对象,由线程独占,并且只能被占有它的线程修改 2、共享只读: 一...

  • String为什么要设计不可变的?

    (1)不可变的原理 (2)不可变的原因和好处 安全:多线程下对资源做写操作有危险。不可变对象不能被写,所以线程安全...

  • 13.字符串

    String对象是不可变的 StringBuilder:线程不安全StringBuffer:线程安全,开销比Sti...

  • 高并发编程05 ~ 线程安全策略

    前面介绍了那么多,那么我们在平时编程的时候应该如何保证我们的代码能够安全的执行呢? 安全策略 不可变对象只要对象创...

网友评论

      本文标题:线程安全策略(一)-不可变对象

      本文链接:https://www.haomeiwen.com/subject/xxadsftx.html