专栏中心

EEPW首页 > 专栏 > 扣丁学堂Java培训之单例设计模式的线程同步

扣丁学堂Java培训之单例设计模式的线程同步

发布人:扣丁客1 时间:2020-12-24 来源:工程师 发布文章

单例模式是最常用的设计模式之一,目的是保证一个类只有一个实例。

在项目中的作用:


1、解决因为频繁创建对象,导致资源消耗过大的问题,如:数据库的连接池,连接池用于创建数据库连接,并对连接进行回收使用,能减少数据库连接的创建次数,从而提高效率,但是连接池对象本身在项目中只需要一个,就需要使用单例模式。类似的还有线程池等。

2、项目中能共享的工具类,如Java中的Runtime类能提供各种运行环境系统参数,它就被设计成了单例模式。

实现单例的过程:

1、要保证类只能创建一个对象,就必须隐藏类的构造方法,所以要将构造方法定义为私有的

2、在类中调用构造方法创建对象,定义静态方法用于返回对象。

下面这种单例模式属于饿汉式单例模式,既一开始就将对象实例化。这样的做法会导致性能的降低,一般我们会采用延迟加载的方式,既需要对象时再实例化。

  classHunger{
  //静态的实例
  privatestaticHungerhunger=newHunger();
  //隐藏构造方法
  privateHunger(){}
  //返回静态实例
  publicstaticHungergetInstance(){
  returnhunger;
  }
  }


下面这种是懒汉式单例模式,既开始不实例化对象,到需要该实例时再实例化,提高了运行效率。

  publicclassLazySingleton{
  //静态的实例
  privatestaticLazySingletonsingle=null;
  //隐藏构造方法
  privateLazySingleton(){
  System.out.println("创建LazySingleton对象");
  }
  //返回静态实例
  publicstaticLazySingletongetInstance(){
  if(single==null){
  single=newLazySingleton();
  }
  returnsingle;
  }
  }


线程安全问题:懒汉单例模式在单线程环境没有问题,但在多线程环境下就会出现问题。

执行代码,"创建LazySingleton对象"这句话会输出多次,也就是创建了多个对象。

  for(inti=0;i<100;i++){
  newThread(newRunnable(){
  @Override
  publicvoidrun(){
  System.out.println(LazySingleton.getInstance());
  }}).start();
  }


分析原因:

假设线程1满足getInstance方法中single==null条件后,准备执行创建对象的代码,然后CPU被其它线程抢占,其它线程在getInstance方法中创建对象,然后线程1抢回CPU继续执行刚才未完成的创建对象代码,这样就创建了多个对象。

线程同步问题的解决方法:

1、使用同步方法

publicstaticsynchronizedLazySingletongetInstance(){
if(single==null){
single=newLazySingleton();
}
returnsingle;
}

执行刚才多线程的代码后,我们发现可以解决同步问题,但是同步方法存在的问题是每个线程进入后都会加锁,执行效率低。

2、使用同步代码块配合if使用

publicstaticLazySingletongetInstance(){
if(single==null){
synchronized(LazySingleton.class){
single=newLazySingleton();
}
}
returnsingle;
}


同步块和if语句配合使用,解决了每次都执行上锁导致的性能问题,但是运行代码后我们会发现,多线程同步的问题还是可能出现,原因是多个线程还是可能会同时进入if语句。

3、使用双重判断

在同步块中再添加一次if判断就解决了上面的问题,因为就算多个线程同时进入外层if语句,执行同步块还是要进行一次判断,这样第一个线程创建对象后,后面的线程就不能再创建了。

  publicstaticLazySingletongetInstance(){
  //外层的if主要作用是判断是否需要执行同步块,提高性能
  if(single==null){
  //静态方法中将类作为锁
  synchronized(LazySingleton.class){
  //判断对象是否为空,为空就创建对象
  if(single==null){
  single=newLazySingleton();
  }
  }
  }
  returnsingle;
  }


4、静态内部类

这种方法结合了饿汉式和懒汉式的特点,如果不调用getInstance方法,静态内部类中的创建对象代码不会执行,调用getInstance后才会执行,也就有了懒汉式延迟加载的效果,并且由于对象是直接创建的,还不存在线程同步问题。

  classMySingleton{
  privateMySingleton(){
  }
  privatestaticclassSingletonHelp{
  staticMySingletoninstance=newMySingleton();
  }
  publicstaticMySingletongetInstance(){
  returnSingletonHelp.instance;
  }
  }



总结:单例模式的实现一般有饿汉式、懒汉式和静态内部类等方式,饿汉式创建对象的性能比较低但不存在线程同步问题,懒汉式由于是延迟加载性能更高,但存在线程同步问题,需要使用双重判断解决,静态内部类的方式也能实现单例模式但是代码可读性稍差。

如果项目对性能不敏感推荐使用饿汉式,如果是单线程环境可以使用一般的懒汉式,如果需要多线程则可以使用多重判断的懒汉式或静态内部类实现。

以上就是关于Java开发单例设计模式线程同步的详细介绍,最后想要了解更多可以登录扣丁学堂官网咨询。扣丁学堂是专业的Java培训机构,不仅有专业的老师和与时俱进的课程体系,还有大量的Java视频教程供学员观看学习,想要学好JavaEE的小伙伴抓紧时间行动吧。扣丁学堂java技术交流群:487098661。微信号:codingbb

专栏文章内容及配图由作者撰写发布,仅供工程师学习之用,如有侵权或者其他违规问题,请联系本站处理。 联系我们

关键词:

相关推荐

InstaSPIN-无刷直流电机与DRV- 8312和Stellaris LM3S818

视频 2011-12-27

高电压与低电压的控制器的测量

视频 2011-12-28

美女诱惑

hpnet 2004-05-16

互补管脉冲电路

固定式三端稳压器输出电压可调电路

罗唯仁靠“20箱台积电机密”换来什么职位? 最新工作疑曝光了

机外型彩电交流全自动关机电路

红外遥控接收电路(T9149A)

电机预驱动

视频 2011-12-28

过压或欠压动作电路

资源下载 2007-12-26

AMD在桌面CPU市场份额中创纪录 对抗英特尔

消费电子 2025-11-24

面对英伟达的DGX机顶盒,苹果展示了搭载万亿参数AI模型的Thunderbolt 5 Mac

智能计算 2025-11-24

ChatGPT的新个性并没有让它感觉更有人情味

智能计算 2025-11-24

长鑫存储发布DDR5和LPDDR5X新品

InstaSPIN_BLDC电机控制解决方案简介

视频 2011-12-28

中国汽车业要变“强”? 专家曝供应链3大定时炸弹

汽车电子 2025-11-24

什么是玻璃纤维织物,为什么T-Glass对AI服务器至关重要?

电机驱动器和电机信号链的简介

视频 2011-12-28

OpenAI与富士康联手,目标是下一代AI硬件制造

英特尔EMIB成台积电CoWoS替代选项?

功率二极管与整流技术解析:结构特性、工作机理与半波整流实现

EDA/PCB 2025-11-24
更多 培训课堂
更多 焦点
更多 视频

技术专区