概述
确保只有一个实例,而且自行实例化并向整个系统提供这个实例。
例如:线程池,servlet,application作用域,缓存等等。
选择单例模式就是为了避免不一致的状态。
常见的单例模式
1、懒汉式
2、饿汉式
3、静态内部类
特点
1、只有一个实例
2、必须是自己创建自己的唯一实例
3、必须给所有其他对象提供这一对象的实例获取方法
第一种、单例模式之饿汉模式
package com.xjion.singleton;
/**
* 单例模式之饿汉模式
* 特点:
* 1)效率高
* 2)线程安全
* 3)不支持延时加载(懒加载)
*/
public class Singleton {
//私有化构造器
private Singleton(){}
//持有一个唯一的对象
private static Singleton singleton=new Singleton();
//给一个返回对象的方法
public static Singleton getInstance(){
return singleton;
}
}
第二种、单例模式之懒汉模式
package com.xjion.singleton;
/**
* 单例模式之懒汉模式
* 特点:
* 1)效率低
* 2)线程安全
* 3)支持延时加载(懒加载)
*/
public class Singleton2 {
//私有化构造器
private Singleton2(){}
//自己持有一个自己的对象
private static Singleton2 singleton2;
//给一个返回对象的方法
public synchronized static Singleton2 getInstance(){
if(singleton2==null){
singleton2=new Singleton2();
}
return singleton2;
}
}
第三种、单例模式之静态内部类模式
package com.xjion.singleton;
/**
* 单例模式之静态内部类
* 特点:
* 1)效率偏高
* 2)线程安全
* 3)支持延时加载
*/
public class Singleton3 {
//私有化构造器
private Singleton3(){}
//持有一个自己的对象
private static class Temp{
private static Singleton3 singleton3=new Singleton3();
}
//给一个返回对象的方法
public static Singleton3 getInstance(){
return Temp.singleton3;
}
}
测试
package com.xjion.singleton;
import java.util.concurrent.CountDownLatch;
public class Test {
public static void main(String[] args) throws InterruptedException {
// Singleton singleton1=Singleton.getInstance();
// Singleton singleton2=Singleton.getInstance();
// System.out.println(singleton1==singleton2);
// Singleton2 singleton1=Singleton2.getInstance();
// Singleton2 singleton2=Singleton2.getInstance();
// System.out.println(singleton1==singleton2);
// Singleton3 singleton1=Singleton3.getInstance();
// Singleton3 singleton2=Singleton3.getInstance();
// System.out.println(singleton1==singleton2);
//线程计数器
int count=10;
final CountDownLatch latch=new CountDownLatch(count);
long startTime=System.currentTimeMillis();
for(int i=1;i<=count;i++){
new Thread(new Runnable() {
@Override
public void run() {
for(int i=1;i<=1000000;i++){
// Singleton.getInstance();
// Singleton2.getInstance();
Singleton3.getInstance();
}
//计数器自减
latch.countDown();
}
}).start();
}
//等待十个线程结束
latch.await();
long endTime=System.currentTimeMillis();
System.out.println("总共耗时:"+(endTime-startTime)+"毫秒!");
}
}
三者之间各有千秋,看情况使用!!!