单例模式

单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。单例模式是一种对象创建型模式。

单例模式:就是确保对象只有一个。

满足的条件:

(1)构造方法私有

(2)提供当前对象作为属性

(3)提供一个共有的方法,返回当前对象的实例


满足单例模式有以下几种写法  :

(1)饿汉式

package singleton;


public class EagerSingleton {


/**
* @yy
* 饿汉式
*/

private int count=0;
private EagerSingleton(){
this.count++;
}

private static EagerSingleton singleton=new EagerSingleton();

public static EagerSingleton getInstance(){
return singleton;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}


public static void main(String[] args) {

EagerSingleton singleton=EagerSingleton.getInstance();
System.out.println(singleton.getCount());
EagerSingleton singleton1=EagerSingleton.getInstance();
System.out.println(singleton1.getCount());
}


}

(2)懒汉式

package singleton;


/*
 * yy
 * 懒汉式
 * */
public class LazySingleton {


private static int count=0;
private LazySingleton(){
count++;
}

private static LazySingleton singleton=null;

/*对于高并发的情况下,使用synchronized关键字,会使整个系统的并发性能下降,synchronized是
* 重量级的锁,因此需要慎重的使用
*/

public  synchronized static LazySingleton getInstance(){
if(singleton==null){
singleton=new LazySingleton();
}
return singleton;
}

public static int getCount() {
return count;
}
public static void setCount(int count) {
LazySingleton.count = count;
}

public static void main(String[] args) {
LazySingleton object=LazySingleton.getInstance();
System.out.println(object.getCount());
LazySingleton object1=LazySingleton.getInstance();
System.out.println(object1.getCount());

}


}

由于多线程的并发,饿汉式不会有任何的问题,但是懒汉式会出现创建多个对象的情况。

(3)在懒汉式的基础上提出双重检查的策略

package singleton;


public class LazySingleton_DoubleCheck {


/**
* @yy

*/

/*关键字volatile的使用,在多线程情况下,volatile修饰的变量不能被修改,否则会出现不一致性
* volatile底层主要主要使用的CAS+不断的重试
* volatile修饰的变量,每一次都是从内存中获取新的值。
* 这个双重检查,主要就是可以减少synchronized锁的线程切换
*/

private int count=0;
private volatile static LazySingleton_DoubleCheck singleton=null;

private LazySingleton_DoubleCheck(){
count++;
}

public static LazySingleton_DoubleCheck getInstance(){
if(singleton==null){
synchronized(LazySingleton_DoubleCheck.class){
if(singleton==null){
singleton=new LazySingleton_DoubleCheck();
}
}
}
return singleton;
}

public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}


public static void main(String[] args) {
for(int i=0;i<30;i++){
new Thread(){
public void run(){
LazySingleton_DoubleCheck instance=LazySingleton_DoubleCheck.getInstance();
System.out.println(Thread.currentThread().getName()+"-------------count:  "+instance.getCount());
}
}.start();

new Thread(){
public void run(){
LazySingleton_DoubleCheck instance=LazySingleton_DoubleCheck.getInstance();
System.out.println(Thread.currentThread().getName()+"-------------count:  "+instance.getCount());
}
}.start();

}
}


}

饿汉式与懒汉式的区别:

饿汉式单例类在类被加载时就将自己实例化,它的优点在于无须考虑多线程访问问题,可以确保实例的唯一性;从调用速度和反应时间角度来讲,由于单例对象一开始就得以创建,因此要优于懒汉式单例。但是无论系统在运行时是否需要使用该单例对象,由于在类加载时该对象就需要创建,因此从资源利用效率角度来讲,饿汉式单例不及懒汉式单例,而且在系统加载时由于需要创建饿汉式单例对象,加载时间可能会比较长。

      懒汉式单例类在第一次使用时创建,无须一直占用系统资源,实现了延迟加载,但是必须处理好多个线程同时访问的问题,特别是当单例类作为资源控制器,在实例化时必然涉及资源初始化,而资源初始化很有可能耗费大量时间,这意味着出现多线程同时首次引用此类的机率变得较大,需要通过双重检查锁定等机制进行控制,这将导致系统性能受到一定影响。

(4)使用IoDH的方式,既可以解决饿汉式的内存的问题,也可以解决多线程并发锁开销的问题

package singleton;


public class IoDHSingleton {


/*
* 使用IoDH的方式解决饿汉式以及懒汉式的不足:
* 饿汉式单例类不能实现延迟加载,不管将来用不用始终占据内存;懒汉式单例类线程安全控制烦琐,而且性能受影响。
* */

private IoDHSingleton(){}

private static class HolderClass{
private static final IoDHSingleton singleton=new IoDHSingleton();
}

public static IoDHSingleton getInstance(){
return HolderClass.singleton;
}

public static void main(String[] args){
IoDHSingleton s1,s2;
s1=IoDHSingleton.getInstance();
s2=IoDHSingleton.getInstance();
System.out.println(s1==s2);
}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值