当前位置: 首页 > article >正文

共享模型之不可变

前言

该文章后续还需要进行修改!!


不可变的解释是对象属性不可以更改。

在多线程下,格式转化使用SimpleDateFormat可能会报错。这是因为线程之间互相影响导致。

public class test {
    public static void main(String[] args) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                try {
                    Date parse = simpleDateFormat.parse("2003-6-03");
                    System.out.println(parse);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

多线程下安全格式转化

public class test {
    public static void main(String[] args) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                try {
                    TemporalAccessor parse = dateTimeFormatter.parse("2003-06-03");
                    System.out.println(parse);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

不可变类的设计

以String为例

值使用char数组存储。hash是用来存储哈希值,第一次调用hashCode时存储在hash中做缓存。

  • 属性使用final保证属性是只读,不可以发生更改
  • 类使用final保证方法不能被覆盖,避免子类破坏不可变性

保护性拷贝

public String(char value[]) {

    this.value = Arrays.copyOf(value, value.length);

}

这是String类中的构造方法。对于char数组,如果value引用参数地址的话,当外部char数组发生改变时,String对象中的值也跟着改变。因此要拷贝出一样的char数组让value来引用拷贝出来的地址。

类似于String类容易频繁创建对象,这时通常会用享元模式来减少对象的创建。JDK使用了享元模式的源码解析

DIY一个连接池

连接池作用是可以避免在高并发的情况下反复建立连接浪费系统性能,实现连接复用。基于享元模式实现的。

class Test{
    public static void main(String[] args) {
        pool pool = new pool(3);
        for (int i = 0; i < 5; i++) {
            new Thread(()->{
                Connection connect = pool.getConnect();
                try {
                    Thread.sleep(new Random().nextInt(1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                pool.freeConnect(connect);
            }).start();
        }
    }
}

public class pool {
    //连接池大小
    private final int poolSize;
    //连接对象数组
    private Connection[] connections;
    //连接对象状态 0表示空闲。1是繁忙
    private AtomicIntegerArray states;

    public pool(int poolSize) {
        this.poolSize = poolSize;
        this.connections = new Connection[poolSize];
        this.states = new AtomicIntegerArray(new int[poolSize]);
        for (int i = 0; i < poolSize; i++) {
            connections[i] = new MyConnect("nameIs"+i);
        }
    }

    //获取连接
    public Connection getConnect(){
        while (true){
            for (int i = 0; i < poolSize; i++) {
                if (states.get(i)==0){
                    if (states.compareAndSet(i,0,1)){
                        System.out.println("获取连接"+connections[i]);
                        return connections[i];
                    }
                }
            }
            //如果没有空闲连接
            synchronized (this){
                try {
                    System.out.println("没有空闲连接");
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //释放连接
    public void freeConnect(Connection connection){
        //判断传过来的连接是否是连接池中的。
        for (int i = 0; i < poolSize; i++) {
            if (connections[i]==connection){
                //因为只有一个线程拿到该连接,因此不会发生线程安全问题,直接使用set即可
                states.set(i,0);
                System.out.println("释放连接:"+connection);
                synchronized (this){
                    this.notifyAll();
                }
                break;
            }
        }
    }
}

获取连接MyConnect{name='nameIs0'}

获取连接MyConnect{name='nameIs1'}

没有空闲连接

获取连接MyConnect{name='nameIs2'}

没有空闲连接

释放连接:MyConnect{name='nameIs0'}

获取连接MyConnect{name='nameIs0'}

没有空闲连接

释放连接:MyConnect{name='nameIs2'}

获取连接MyConnect{name='nameIs2'}

释放连接:MyConnect{name='nameIs0'}

释放连接:MyConnect{name='nameIs2'}

释放连接:MyConnect{name='nameIs1'}


http://www.kler.cn/a/147353.html

相关文章:

  • cocosCreator视频web模式播放踩坑解决
  • python怎么加锁
  • 中仕公考怎么样?事业编面试不去有影响吗?
  • 【Linux】Ubuntu中muduo库的编译环境安装
  • 《AI 之影》
  • 数据结构-哈夫曼树
  • C#中的警告CS0120、CS0176、CS0183、CS0618、CS0649、CS8600、CS8601、CS8602、CS8604、CS8625及处理
  • Rust语言入门教程(六) - 字符串类型
  • 百度人工智能培训第一天笔记
  • 多线程04 死锁,线程可见性
  • 任务管理器怎么打开?4个方法快速打开!
  • Vue 2.0源码分析-实例挂载的实现
  • 汽车电子 -- 车载ADAS之DOW(开门预警 )
  • docker容器运维操作命令
  • CF 1896 A. Jagged Swaps 学习笔记
  • 【STM32】GPIO输入
  • Android Bitmap 模糊效果实现 (二)
  • 渠道运营常用的ChatGPT通用提示词模板
  • 解决几乎任何机器学习问题 -- 学习笔记(组织机器学习项目)
  • 自动化任务:探索 Shell 脚本的实际应用
  • git 无法可克隆分支 时候使用tortoisegit
  • 工具推荐 sejda pdf一个可以将pdf转为txt的工具
  • Vue基础入门(三):Vue3的使用
  • 扫地机器人市场持续火爆,景联文科技数据采集标注方案助力扫地机器人智能化升级
  • C++ Qt QVariant类型使用介绍与代码演示
  • MATLAB实战 | 不同形式的三维曲面图