• 多线程新手村3--多线程代码案例


    1.1 单例模式

    单例模式是设计模式中非常经典的一种。那么有同学肯定就会好奇了,什么是设计模式呢?

    设计模式简单的说就是程序员的“棋谱”,我们下象棋时肯定或多或少都背过棋谱,例如当头炮、马后炮等,设计模式也是这样,开发过程中常常会遇到一些经典场景,用固定的解决方案去解决这些问题,这就是设计模式,今天我们先来介绍一下单例模式。

    单例模式是指某个类只能实例化一个对象,不能有多个,这一点在很多场景中都会用到,例如数据库中的DateSource实例就只需要一个;单例模式又有两种实现方式,分别为饿汉模式和懒汉模式。

    1.1.1 饿汉模式

    在类加载的时候,创建实例(比较急切)

    可以看到,由于将构造方法设为私有,所以当我们想要自己实例化一个对象的时候,编译器会报错,此时,这个类将只会有加载类时实例化的那一个对象,无法再实例化出其它对象。

    1.1.2 懒汉模式

    只有当需要的时候才创建实例

    上述代码可以看出,只有当首次调用getInstance方法时才会创建实例,否则将不会创建实例。

    单线程中懒汉模式没有问题,但是放在多线程中,就会存在许多bug!

    1.1.3 懒汉模式(多线程版)

    首先要解决一个疑惑,为什么饿汉模式的单线程都不会有bug,但是懒汉模式的多线程会存在bug呢?是因为饿汉模式的getInstance方法只有读功能,但是懒汉模式的getInstance方法却既可读又可写,两个线程对于同一个变量进行写操作,就很容易出现问题。所以我们要加锁,将操作变为原子性的,这样就不会出现问题了。

    1、这里的加锁是为了保证原子性操作,防止代码出bug(new多个对象出来)

    2、这里再一次判断对象是否为空是为了确定要不要加锁,因为如果不加这个代码的话,每次调用这个方法都会加锁,但是加锁很费时,效率很低,不好!

    3、此处的volatile关键字是为了防止出现指令重排序问题。

    1.2 阻塞队列

    阻塞队列是多线程代码中常用的一种数据结构。

    所谓阻塞队列,其实就是加了阻塞功能的队列。

    a)如果队列为空,继续出队列,就会发生阻塞,直到其它线程向队列中加入元素。

    b)如果队列为满,继续入队列,也会发生阻塞,直到其它线程向队列中取走元素。

    阻塞队列,最大的意义是用来实现“生产者消费者模型”

    “生产者消费者”模型的意义:

    1、解耦合(单独设置一个队列,使原本两个直接进行数据交互的元素通过这个队列进行交互)

    2、削峰填谷

    当数据请求量很大的时候,如果没有阻塞队列的话,服务器A一直给服务器B发数据,就可能使服务器B崩溃;但是如果设置一个阻塞队列,那么A只需要将数据放入队列中,如果B此时已达到最大处理负荷的话,那B只需要慢慢的取出队列中的数据处理即可;反之,如果此时数据请求量很小,那么服务器B就可以慢慢地消耗掉堆积在阻塞队列中的数据。

    1.3 阻塞队列的代码实现

    以上代码就是自己实现了一个简易的阻塞队列,可以用作一个简单的“生产者消费者”模型。注意两个wait和notify都是互相唤醒的,无法自己唤醒自己。

  • 相关阅读:
    Java中Map详解
    Spring Boot 中的 @CacheEvict 注解使用
    针对垃圾渗滤液中膜产水脱氮工艺的设计,除氨氮树脂
    关系型数据库(一)---关系数据模型与关系
    LeetCode每日一题(2365. Task Scheduler II)
    输电线路故障诊断(Python代码,逻辑回归、决策树、随机森林、XGBoost和支持向量机五种不同方法诊断)
    算法训练 第八周
    猿创征文 |《深入浅出Vue.js》打卡Day3
    Redis中常见数据结构和数据类型
    nacos
  • 原文地址:https://blog.csdn.net/qq_62872261/article/details/139244887