JAVA多线程并发下的单例模式应用_第1页
JAVA多线程并发下的单例模式应用_第2页
JAVA多线程并发下的单例模式应用_第3页
JAVA多线程并发下的单例模式应用_第4页
JAVA多线程并发下的单例模式应用_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

本文格式为Word版,下载可任意编辑——JAVA多线程并发下的单例模式应用JAVA多线程并发下的单例模式应用

单例模式理应是设计模式中对比简朴的一个,也是分外常见的,但是在多线程并发的环境下使用却是不那么简朴了,今天我给大家共享一个在开发过程中遇到的单例模式的应用。

单例模式理应是设计模式中对比简朴的一个,也是分外常见的,但是在多线程并发的环境下使用却是不那么简朴了,今天给大家共享一个我在开发过程中遇到的单例模式的应用。

首先我们先来看一下单例模式的定义:

一个类有且仅有一个实例,并且自行实例化向整个系统供给。

单例模式的要素:

1.私有的静态的.实例对象

2.私有的构造函数保证在该类外部,无法通过new的方式来创造对象实例

3.公有的、静态的、访问该实例对象的方法

单例模式分为懒汉形和饿汉式

懒汉式:

应用刚启动的时候,并不创造实例,当外部调用该类的实例或者该类实例方法的时候,才创造该类的实例。时间换空间

优点:实例在被使用的时候才被创造,可以节省系统资源,表达了延迟加载的思想。

缺点:由于系统刚启动时且未被外部调用时,实例没有创造;假设一时间有多个线程同时调用LazySingleton.getLazyInstance方法很有可能会产生多个实例。

例子:

publicclassSingletonClass

//私有构造函数,保证类不能通过new创造

privateSingletonClass

privatestaticSingletonClassinstance=null;

publicstaticSingletonClassgetInstance

ifinstance==null

//创造本类对象

instance=newSingletonClass;

returninstance;

饿汉式:

应用刚启动的时候,不管外部有没有调用该类的实例方法,该类的实例就已经创造好了。空间换时间。

优点:写法简朴,在多线程下也能保证单例实例的唯一性,不用同步,运行效率高。

缺点:在外部没有使用到该类的时候,该类的实例就创造了,若该类实例的创造对比消耗系统资源,并且外部一向没有调用该实例,那么这片面的系统资源的消耗是没有意义的。

例子:

publicclassSingleton

//首先自己在内部定义自己的一个实例,只供内部调用

privatestaticfinalSingletoninstance=newSingleton;

//私有构造函数

privateSingleton

//供给了静态方法,外部可以直接调用

publicstaticSingletongetInstance

returninstance;

下面模拟单例模式在多线程下会展现的问题

/**

*懒汉式单例类

*/

publicclassLazySingleton

//为了易于模拟多线程下,懒汉式展现的问题,我们在创造实例的构造函数里面使当前线程暂停了50毫秒

privateLazySingleton

try

Thread.sleep50;

catchInterruptedExceptione

e.printStackTrace;

System.out.println生成LazySingleton实例一次!;

privatestaticLazySingletonlazyInstance=null;

publicstaticLazySingletongetLazyInstance

iflazyInstance==null

lazyInstance=newLazySingleton;

returnlazyInstance;

测试代码:我们在测试代码里面新建了10个线程,让这10个线程同时调用LazySingleton.getLazyInstance方法

publicclassSingletonTest

publicstaticvoidmainString[]args

//创造十个线程调

forinti=0;i10;i++

newThread

@Override

publicvoidrun

LazySingleton.getLazyInstance;

.start;

结果:

生成LazySingleton实例一次!

生成LazySingleton实例一次!

生成LazySingleton实例一次!

生成LazySingleton实例一次!

生成LazySingleton实例一次!

生成LazySingleton实例一次!

生成LazySingleton实例一次!

生成LazySingleton实例一次!

生成LazySingleton实例一次!

生成LazySingleton实例一次!

可以看出单例模式懒汉式在多线程的并发下也会展现问题,

分析一下:多个线程同时访问上面的懒汉式单例,现在有两个线程A和B同时访问LazySingleton.getLazyInstance方法。

假设A先得到CPU的时间切片,A执行到iflazyInstance==null时,由于lazyInstance之前并没有实例化,所以lazyInstance==null为true,在还没有执行实例创造的时候

此时CPU将执行时间分给了线程B,线程B执行到iflazyInstance==null时,由于lazyInstance之前并没有实例化,所以lazyInstance==null为true,线程B持续往下执行实例的创造过程,线程B创造完实例之后,返回。

此时CPU将时间切片分给线程A,线程A接着开头执行实例的创造,实例创造完之后便返回。由此看线程A和线程B分别创造了一个实例存在2个实例了,这就导致了单例的失效。

解决手段:我们可以在getLazyInstance方法上加上synchronized使其同步,但是这样一来,会降低整个访问的速度,而且每次都要判断。

那么有没有更好的方式来实现呢?我们可以考虑使用双重检查加锁的方式来实现,就可以既实现线程安好,又能够使性能不受到很大的影响。我们看看概括解决代码

publicclassLazySingleton

privateLazySingleton

try

Thread.sleep50;

catchInterruptedExceptione

e.printStackTrace;

System.out.println生成LazySingleton实例一次!;

privatestaticLazySingletonlazyInstance=null;

publicstaticLazySingletongetLazyInstance

//先检查实例是否存在,假设不存在才进入下面的同步块

iflazyInstance==null

//同步块,线程安好地创造实例

synchronizedLazySingleton.class

//再次检查实例是否存在,假设不存在才真正地创造实例

iflazyInstance==null

lazyInstance=newLazySingleton;

returnlazyInstance;

这样我们就可以在多线程并发下安好应用单例模式中的懒汉模式。这种方法在代码上可能就不怎么美观,我们可以优雅的使用一个内部类来维护单例类的实例,下面看看代码

publicclassGracefulSingleton

privateGracefulSingleton

System.out.println创造GracefulSingleton实例一次!;

//类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载

privatestaticclassSingletonHoder

//静态初始化器,由JVM来保证线程安好

privatestaticGracefulSingletoninstance=newGracefulSingleton;

publicstaticGracefulSingletongetInstance

returnSingletonHoder.instance;

说一下我在实际开发中的场景:为了程序的高效率使用多线程并发,然而是循环调用,可能导致创造线程数过多,考虑采用线程池管理,这时候创造线程池依旧是处于循环调用中,也可能导致多个线程池,这时候就考虑使用单例模式。

源代码:

publicclassThreadPoolFactoryUtil

privateExecutorServiceexecutorService;

//在构造函数中创造线程池

privateThreadPoolFactoryUtil

//获取系统处理器个数,作为线程池数量

intnThreads=Runtime.getRuntime.availableProcessors;

executorService=Executors.newFixedThreadPoolnThreads;

//定义一个静态内部类,内部定义静态成员创造外部类实例

privatestaticclassSingletonContainer

privatestaticThreadPoolFactoryUtilutil=newThreadPoolFactoryUtil;

//获取本类对象

publicstaticThreadPoolFactoryUtilgetUtil

returnSingletonContainer.util;

publicExecutorServicegetExecutorService

returnexecutorService;

涉及到一个静态内部类,我们看看静态内部类的特点:

1、静态内部类无需凭借于外部类,它可以独立于

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论