Android-Java-单例模式优化&多线程并发

上一篇博客,Android-Java单例模式,介绍了在真实开发过程中,普遍使用的几种单例模式,而今天这篇博客,将要对单利模式进行优化 并且 通过多线程并发来分析

单利模式的优化:

对于为什么会出现安全问题,可以看Android-多线程安全问题-synchronized博客

package android.java.thread14;

/**
 * 单例模式优化
 */
public class SingletonPattern {

    private SingletonPattern() {
    }

    /**
     * 俄汉式:多线程并发是安全??的,因为此类一加载就实例化了
     */
    private static final SingletonPattern SINGLETON_PATTERN = new SingletonPattern();

    public static SingletonPattern getInstance1() {
        return SINGLETON_PATTERN; // 如果这里对SINGLETON_PATTERN共享数据进行操作,多线程并发不安全!
    }

    /**
     * 懒汉式:需要进行 静态方法 synchronized(锁?? SingletonPattern.class)
     * 此方式性能低:因为线程每次调用此方法都需要判断锁
     * 需要明白CPU执行执行多线程的随机性,并用以下代码方式解决 多线程并发
     */
    private static SingletonPattern singletonPattern = null;

    public static synchronized SingletonPattern getInstance2() {
        if (null == singletonPattern) { // 这里对singletonPattern共享数据进行操作,多线程并发不安全!
            singletonPattern = new SingletonPattern(); // 这里对singletonPattern共享数据进行操作,多线程并发不安全!
            System.out.println(Thread.currentThread().getName() + ">>>>>>> 懒汉式1 单例模式实例化了");
        }
        return singletonPattern;
    }

    /**
     * 懒汉式:对性能要求高 可以  synchronized + if双重判断
     * 需要明白CPU执行执行多线程的随机性,并用以下代码方式解决 多线程并发
     */
    private static SingletonPattern singleton = null;

    private static final Object objectLock = new Object(); // 定义一把同步锁??

    public static SingletonPattern getInstance3() {
        if (null == singleton) {

            synchronized (objectLock) {

                if (null == singleton) {
                    singleton = new SingletonPattern();
                    System.out.println(Thread.currentThread().getName() + ">>>>>>> 懒汉式2 单例模式实例化了");
                }

            }

        }
        return singleton;
    }
}

多线程并发实例化单例模式:

package android.java.thread14;

/**
 * 执行任务,此任务可以给线程运行
 */
class DoRunnable implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            // doRunnable1();
            // doRunnable2();
            doRunnable3();

            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void doRunnable1() {
        SingletonPattern.getInstance1();
    }

    private void doRunnable2() {
        SingletonPattern.getInstance2();
    }

    private void doRunnable3() {
        SingletonPattern.getInstance3();
    }
}

public class Test {

    public static void main(String[] args) {
        // 实例化任务
        DoRunnable doRunnable = new DoRunnable();

        // 开启三个线程
        new Thread(doRunnable).start();
        new Thread(doRunnable).start();
        new Thread(doRunnable).start();
    }

}

执行结果,CPU随机性:

俄汉式:性能提高的同时 又保证了多线程的并发-安全

/**
     * 懒汉式:对性能要求高 可以  synchronized + if双重判断
     * 需要明白CPU执行执行多线程的随机性,并用以下代码方式解决 多线程并发
     */
    private static SingletonPattern singleton = null;

    private static final Object objectLock = new Object(); // 定义一把同步锁??

    public static SingletonPattern getInstance3() {

        // 假设CPU随机第四步:Thread-1 现在判断不为null,进不去
        if (null == singleton) {
            // 假设CPU随机第一步:Thread-0 执行到这里CPU去执行其他Thread-2线程了     假设CPU随机第二步:Thread-2线程在这里判断锁,然后进去了
            synchronized (objectLock) {

                if (null == singleton) {
                    singleton = new SingletonPattern();
                    System.out.println(Thread.currentThread().getName() + ">>>>>>> 懒汉式2 单例模式实例化了");
                }

            } // 假设CPU随机第三步:Thread-2 执行完毕

        }
        return singleton;
    }

原文地址:https://www.cnblogs.com/android-deli/p/10236266.html

时间: 2024-11-18 15:48:14

Android-Java-单例模式优化&多线程并发的相关文章

Java - 单例模式与多线程

单例模式大家并不陌生,分为饿汉式和懒汉式等. 线程安全的饿汉式单例 饿汉式单例在类第一次加载的时候就完成了初始化,上代码: public class MyObject { private static MyObject myObject = new MyObject(); public static MyObject getInstance(){ return myObject; } } 下面来验证饿汉式单例的线程安全性: public class MyThread extends Thread

java工程优化——多线程下的单例模式

在最初学习设计模式时,我为绝佳的设计思想激动不已,在以后的工程中,多次融合设计模式,而在当下的设计中,我们已经觉察出了当初设计模式的高瞻远瞩,但是也有一些不足,需要我们去改进,有人说过,世界上没有绝对的事,当然,再简单的事情,环境变了,也会发生变化,今天和大家一起分享在多线程下单例模式的优化. 1,传统 首先,我们回顾下传统的单例(懒汉式)是如何工作的: public class SingletonClass{ private static SingletonClass instance=nul

你所不知道的单例模式和多线程并发在单例模式中的影响

单例对象(Singleton)是一种常用的设计模式.在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在.这样的模式有几个好处: 1.某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销. 2.省去了new操作符,降低了系统内存的使用频率,减轻GC压力. 3.有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了.(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程. 首先

[Java复习05] 多线程&amp;并发 知识点补充

0. wait/notify/notifyAll的理解? wait:让持有该对象锁的线程等待: notify: 唤醒任何一个持有该对象锁的线程: notifyAll: 唤醒所有持有该对象锁的线程: 它们 3 个的关系是,调用对象的 wait 方法使线程暂停运行,通过 notify/ notifyAll 方法唤醒调用 wait 暂时的线程. 它们并不是 Thread 类中的方法,而是 Object 类中的,为什么呢? 因为每个对象都有监视锁,线程要操作某个对象当然是要获取某个对象的锁了,而不是线程

浅淡java单例模式结合多线程测试

本人才疏学浅,正好利用博客这个平台整理下思路 使用单例模式简单来说生成对象时属性都一样,即你new一百次,通过方法得到的结果都一样(比如获取静态资源文件,工具类等). 所以就没必要生成多个对象浪费服务器内存,他和静态类又不同,因为单例本质也是对象系统,长期不使用,也会给cg清除.但是静态类不同,静态类的成员变量和有静态方法会在程序的整个生命周期存在,比如在服务器内在中加载后服务器不关,就会一直存在,同理的有servlet的ServletContext对象和jsp的application对象 单例

Android中Sqlite数据库多线程并发问题

最近在做一个Android项目, 为了改善用户体验,把原先必须让用户"等待"的过程改成在新线程中异步执行.但是这样做遇到了多个线程同时需要写Sqlite数据库,导致操作数据库失败. 本人对Java并不熟悉,只接触了2个多月(纯粹为了Android项目, 才开始接触JAVA), 在网上搜了一下, 发现JAVA在线程同步方面提供的功能相对于C#真少,只找到synchronized关键字, 而且还不提供timeout机制, 不过经过测试, 至少解决了目前的需求. 问题需求: 1. Andro

java单例模式,多线程下实现

单例模式 必备条件: 1:private的构造方法. 2:private static 对象保存该类实例. 3:static方法返回该类实例. (一)饿汉模式 /** * 单例模式 * 1:线程安全实现 * 2:浪费内存 * @author 祥少 * */public class SingletonTest { //final关键字,导致一旦被初始化,一直占用该段内存(即使你不使用)    public static final SingletonTest singletonTest = new

【JAVA面试题】设计单例模式的多线程实现

在阅读的过程中有任何问题,欢迎一起交流 邮箱:[email protected]    QQ:1494713801 单例模式是设计模式中最简单的形式之一.这一模式的目的是使得类的一个对象成为系统中的唯一实例.要实现这一点,可以从客户端对其进行实例化开始.因此需要用一种只允许生成对象类的唯一实例的机制,"阻止"所有想要生成对象的访问.使用工厂方法来限制实例化过程.这个方法应该是静态方法(类方法),因为让类的实例去生成另一个唯一实例毫无意义. 代码如下: [java] public cla

Java 多线程并发编程面试笔录一览

知识体系图: 1.线程是什么? 线程是进程中独立运行的子任务. 2.创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法 方式二:声明实现 Runnable 接口的类.该类然后实现 run 方法 推荐方式二,因为接口方式比继承方式更灵活,也减少程序间的耦合. 3.获取当前线程信息? Thread.currentThread() 4.线程的分类 线程分为守护线程.用户线程.线程初始化默认为用户线程. setDaemon(true) 将该线程标记为