Java 实现一个单例模式_Java实现单例模式的两种方式

单例模式在实际开发中有很多的用途,比如我们在项目中常用的工具类,数据库等资源的连接类。这样做的好处是避免创建多个对象,占用内存资源,自始自终在内存中只有一个对象为我们服务。

单例对象一般有两种实现方式。懒汉式和饿汉式。

饿汉式实现如下:

packagecom.day05;/*** 饿汉式

*

*@authorAdministrator

**/

public classSingle {//定义一个个私有静态本类对象变量,饿汉式是一上来就给该变量进行初始化,加上final是让s这个对象引用始终保持不变,更为严谨

private static final Single s = newSingle();//构造方法私有化,让外部无法通过new 关键字来进行创建对象

privateSingle() {

}//暴露出一个外界可以获取该类对象的公共静态方法

public staticSingle getInstance() {returns;

}

}

测试类:

packagecom.day05;public classSingleDemo {public static voidmain(String[] args) {

Single s1=Single.getInstance();

Single s2=Single.getInstance();

System.out.println(s1==s2);

}

}

运行结果:

true

即s1==s2说明了,s1和s2在内存中地址都相等,即s1、和s2是同一个对象。

懒汉式实现如下:

packagecom.day05;/*** 懒汉式

*

*@authorAdministrator

**/

public classSingle {//定义一个个私有静态本类对象变量,懒汉式是先赋值为null,当需要的时候在初始化

private static Single s = null;//构造方法私有化,让外部无法通过new 关键字来进行创建对象

privateSingle() {

}//暴露出一个外界可以获取该类对象的公共静态方法

public staticSingle getInstance() {if (s == null)

s= newSingle();returns;

}

}

以上的代码如果是单线程的话就不会存在问题,但是当有多线程操作的时候,就会存在线程安全问题,演示代码如下:

packagecom.day05;/*** 懒汉式

*

*@authorAdministrator

**/

public classSingle {//定义一个个私有静态本类对象变量,懒汉式是先赋值为null,当需要的时候在初始化

private static Single s = null;//构造方法私有化,让外部无法通过new 关键字来进行创建对象

privateSingle() {

}//暴露出一个外界可以获取该类对象的公共静态方法

public staticSingle getInstance() {if (s == null) {try{

Thread.sleep(1000L);

}catch(InterruptedException e) {

e.printStackTrace();

}

s= newSingle();

}returns;

}

}

测试类如下:

packagecom.day05;public class SingleDemo implementsRunnable {public static voidmain(String[] args) {

SingleDemo sd= newSingleDemo();newThread(sd).start();newThread(sd).start();

}

@Overridepublic voidrun() {

Single s=Single.getInstance();

System.out.println(s);

}

}

运行结果如下:

com.day05.Single@4081b5a4

com.day05.Single@64dcdaac

可以发现每次运行结果打印出获取对象不是同一个,即存在线程安全问题。

问题分析:

67d0283fdb9526eb0f12a5d0788997a0.png

由此我们可以采用Java给我们提供的同步锁来解决以上的问题,修改代码如下:

packagecom.day05;/*** 懒汉式

*

*@authorAdministrator

**/

public classSingle {//定义一个个私有静态本类对象变量,懒汉式是先赋值为null,当需要的时候在初始化

private static Single s = null;//构造方法私有化,让外部无法通过new 关键字来进行创建对象

privateSingle() {

}//暴露出一个外界可以获取该类对象的公共静态方法

public static synchronizedSingle getInstance() {if (s == null) {try{

Thread.sleep(1000L);

}catch(InterruptedException e) {

e.printStackTrace();

}

s= newSingle();

}returns;

}

}

这样就解决了上面的代码存在的线程安全问题,但是同步锁虽然可以解决了线程安全问题,但是却会存在效率问题,所以我们可以采用双重判断的方法来优化一下改代码如下所示:

packagecom.day05;/*** 懒汉式

*

*@authorAdministrator

**/

public classSingle {//定义一个个私有静态本类对象变量,懒汉式是先赋值为null,当需要的时候在初始化

private static Single s = null;//构造方法私有化,让外部无法通过new 关键字来进行创建对象

privateSingle() {

}//暴露出一个外界可以获取该类对象的公共静态方法//这里需要注意的使静态共享数据使用的使该类的字节码对象即Single.class

public staticSingle getInstance() {//这里增加了一次判断,可以少一次进行锁的处理

if (s == null) {synchronized (Single.class) {if (s == null) {try{

Thread.sleep(1000L);

}catch(InterruptedException e) {

e.printStackTrace();

}

s= newSingle();

}

}

}returns;

}

}

总结:还是比较推荐使用饿汉式,因为写法简单,不存在线程安全问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值