单例模式与多线程
单例模式就是全局唯一但是所有程序都可以使用的对象
写单例模式步骤:
1.将构造函数设置为私有的
2.创建一个静态的类变量
3.提供获取单例的方法
立即加载/饿汉模式
/** * user:ypc; * date:2021-06-13; * time: 21:02; */ //饿汉方式实现单例模式 public class Singleton { //1.将构造函数设置为私有的,不然外部可以创建 private Singleton (){ } //2.创建静态的类变量(让第三步的方法进行返回) private static Singleton singleton = new Singleton (); //给外部接口提供的获取单例的方法 public static Singleton getInstance (){ return singleton ; } }测试饿汉的单例模式
//测试饿汉方式实现的单例模式,创建两个线程,看是不是得到了一个实列对象,如果为true就说明饿汉的单例模式没有问题 static Singleton singleton1 = null ; static Singleton singleton2 = null ; public static void main ( String [] args ) throws InterruptedException { Thread thread1 = new Thread (() -> { singleton1 = Singleton . getInstance (); }); Thread thread2 = new Thread (() -> { singleton2 = Singleton . getInstance (); }); thread1 . start (); thread2 . start (); thread1 . join (); thread2 . join (); System . out . println ( singleton1 == singleton2 ); }
延时加载/懒汉模式
不会随着程序的启动而启动,而是等到有人调用它的时候,它才会初始化
/** * user:ypc; * date:2021-06-13; * time: 21:22; */ //懒汉方式实现单例模式 public class Singleton2 { static class Singleton { //1.设置私有的构造函数 private Singleton () { } //2.提供一个私有的静态变量 private static Singleton singleton = null ; //3.提供给外部调用,返回一个单例对象给外部 public static Singleton getInstance () { if ( singleton == null ) { singleton = new Singleton (); } return singleton ; } } }那么这样写有什么问题呢?我们来看看多线程情况下的懒汉方式实现单例模式:
/** * user:ypc; * date:2021-06-13; * time: 21:22; */ //懒汉方式实现单例模式 public class Singleton2 { static class Singleton { //1.设置私有的构造函数 private Singleton () { } //2.提供一个私有的静态变量 private static Singleton singleton = null ; //3.提供给外部调用,返回一个单例对象给外部 public static Singleton getInstance () throws InterruptedException { if ( singleton == null ) { Thread . sleep ( 100 ); singleton = new Singleton (); } return singleton ; } } static Singleton singleton1 = null ; static Singleton singleton2 = null ; public static void main ( String [] args ) throws InterruptedException { Thread thread1 = new Thread (() -> { try { singleton1 = Singleton . getInstance (); } catch ( InterruptedException e ) { e . printStackTrace (); } }); Thread thread2 = new Thread (() -> { try { singleton2 = Singleton . getInstance (); } catch ( InterruptedException e ) { e . printStackTrace (); } }); thread1 . start (); thread2 . start (); thread1 . join (); thread2 . join (); System . out . println ( singleton1 == singleton2 ); } }结果:
所以发生了线程不安全的问题
那么要如何更改呢?
加锁:
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did214565