栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

多线程相关的一些设计模式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

多线程相关的一些设计模式

这一节,我们主要来探讨一些多线程相关的设计模式。

单例模式

单例模式,顾名思义,是能够保证某个类在程序中只能创建一个实例的设计模式。
其对象的实例化被限制了,只能创建一个,多了的创建不了。

在java中,通过

  • 使用静态成员表示实例(唯一性)
  • 让构造方法私有的方法(堵住了new创建实例的扣子)

来实现。
单例模式有饿汉模式和懒汉模式两种。

饿汉模式

饿汉模式:程序启动,立刻创建实例

class Singleton{
    private static Singleton instance = new Singleton();
    
    public static Singleton getInstance(){
        return instance;
    }
    
    private Singleton(){}
}
懒汉模式

懒汉模式:程序启动,不立刻创建实例;类加载的同时,创建实例

class SingletonLazy{
    private static SingletonLazy instance = null;
    
    public static SingletonLazy getInstance(){
        if(instance == null){
            instance = new SingletonLazy();//写
        }
        return instance;
    }
    
    private SingletonLazy(){}
}
  • 对于饿汉模式,由于只涉及到多线程读,所以它的线程是安全的
  • 对于懒汉模式,创建实例的时候涉及多线程读写,所以线程是不安全的,后面的线程安全
class SingletonLazy{
    volatile private static SingletonLazy instance = null;

    public static SingletonLazy getInstance(){
        if(instance == null){
            synchronized (SingletonLazy.class){
                if(instance == null){
                    instance = new SingletonLazy();
                }
            }
        }
        return instance;
    }

    private SingletonLazy(){}
}

if(instance == null){instance = new SingletonLazy();}这步操作在多线程下,可能会出现多个线程进入if判断,从而创建多个实例。这时候,我们需要用synchronized来限制线程的进入。

另外,由于只是在创建实例的时候可能会出现线程不安全的情况,而synchronized的开销非常大,后期我们要尽可能的避免synchronized,故而在代码块的外面增加一个if(instance == null)的判断,来减小synchronized的开销。

生产者消费者模式

生产者消费者模式的优点:

  • 可以做到更好的“解耦合”
  • 能够做到“削峰填谷”,提高整个系统的抗风险能力
public class Demo19 {

    public static void main(String[] args) {
        BlockingQueue queue = new LinkedBlockingQueue<>();

        Thread customer = new Thread(() -> {
            while(true){
                try {
                    int elem = queue.take();
                    System.out.println("消费了:"+elem);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        customer.start();

        Thread producer = new Thread(() -> {
            int elem = 0;
           while(true){
               System.out.println("生产了:"+elem);
               try {
                   queue.put(elem);
                   elem++;
                   Thread.sleep(800);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }

           }
        });
        producer.start();
    }
}

上述代码使用了一个阻塞队列,这是java自带的,下面我们将模拟实现一下阻塞队列

阻塞队列
class MyBlockingQueue{
    private int[] arr = new int[1000];
    private int head = 0;
    private int tail = 0;
    private int size = 0;

    public void put(int val) throws InterruptedException {
        synchronized (this){
            while(size == arr.length){//此处需要while进行再次判断
                this.wait();
            }
            arr[head] = val;
            tail++;
            if(tail == arr.length){
                tail = 0;
            }
            size++;
            this.notify();
        }
    }

    public Integer take() throws InterruptedException {
        synchronized (this){
            while(size == 0){
                this.wait();
            }
            int ret = arr[head];
            head++;
            if(head == arr.length){
                head = 0;
            }
            size--;
            this.notify();
            return ret;
        }
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1032757.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号