1、单利模式:
核心作用:保证一个类中只有一个实例(对象),并且提供一个访问该实例的全局访问点。(不管你启动了多少个,始终只有一个)
比如windows的TaskManager,Recycle Bean。
优点:单利只生成一个实例,减少了系统性能的开销,减少系统性能开销。可以在系统设置全局访问点,优化共享资源访问。
常见的五种单利模式实现方式:
主要:
饿汉式:(线程安全,调用效率高。但是,不能延时加载。)
懒汉式:(线程安全,调用效率不高,但是,可以延时加载。)
-其他:
双重检测锁式(由于JVM低层内部模型原因,偶尔会出问题。不建议使用)
静态内部类式(线程安全,调用效率高。但是,可能延时加载)
枚举单例(线程安全,调用效率高,不能延时加载)
饿汉式
public class SingletonHungry{
private static /*final*/ SingletonHungry instance = new SingletonHungry();//类初始化的时候加载(没有延时)
private SingletonHungry(){
}
//类加载器加载时本身线程安全。
public static SingletonHungry getInstance(){
return instance;
}
}
懒汉式
public class SingletonLazzy{
//类初始化的时候不实例化对象
private static SingletonLazzy instance;
//私有化构造方法
private SingletonLazzy(){
}
//方法同步,调用效率低
private static synchronized SingletonLazzy getInstance(){
if(instance==null){
instance=new SingletonLazzy;
}
return instance;
}
}
双重检测锁机制
//由于类加载和JVM会调整顺序,所以仅做参考
public class SingletonCheck{
private static SingletonCheck instance=null;
public static SingletonCheck getInstance(){
if(null==instance){
SingletonCheck sc;
synchronized (SingletonCheck.class){
sc=instance;
if(null=sc){
synchronized(SingletonCheck.class){
if(sc==null){
sc=new SingletonCheck();
}
}
instance=sc;
}
}
}
return instance;
}
private SingletonCheck(){
}
}
静态内部类实现方式
//线程安全,调用效率高,并且实现了延时加载
public class SingletonStaticInnerClass{
private static class SingletonClassInstance{
private static final SingletonStaticInnerClass instance = new SingletonstaticInnerClass();
}
private static SingletonStaticInnerClass getInstanc(){
return SingletonClassInstance.instance;
}
private SingletonStaticInnerClass(){
}
}
通过枚举实现单利模式
//避免了反射和序列化的漏洞,调用效率比较高,没有懒加载
public enum SingletonEnum{
//这个枚举,本身就是单利模式
INSTANCE;
//添加自己需要的操作
public void singletonOpreation(){
}
}
测试反射和反序列化破解(除枚举外的)单利模式
public class Client{
public sttic void main (String[]args){
Class<Singleton> clazz=(Class<Singleton>)Class.forName("");
Constructor<Singleton> c = clazz.getDeclaredConstructor(null);
c.setAccessible(true);//跳过检测
Singleton s3 = c.newInstance();
}
}
反破解跳过(除枚举外的其中饿汉式)私有权限检测方式
public class Singleton{
private static Singleton instance =new Singleton();
private Singleton(){//破解反射
if(null!=instance){
throw new RunTimeException();
}
}
public static Singleton getInstance(){
return instance;
}
}
测试反序列化破解序列化的单利
public class Client2{
public static void main (String[]args){
Singleton s1 = Singleton.getInstance();
try{
FileOutputStream fos =new FileOutputStream("d:/a.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObjec(s1);
}catch{
e.printlnStackException();
}finally{
oos.close();
fos.close();
}
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/a.txt"));
Singleton s3=(Singleton)ois.readObject();
System.out.println(s3);
}
}
序列化的单利
public class Singleton implements Serialzable{
private static Singleton instance =new Singleton();
private Singleton(){//破解反射
if(null!=instance){
throw new RunTimeException();
}
}
public static Singleton getInstance(){
return instance;
}
//破解反序列化,这个方法是如果已经有对象了,再调用的时候把原来的调回去,不用再给创建新的对象
private Object readResolve()throws ObjectStreamException{
return instance;
}
}
相对环境测试效率
import java.util.concurrent.CountDownLatch;
/**
* 相对环境下多线程并发测试单利运行效率
* @author Administrator
*
*/
public class Test2 {
public static void main(String[] args) throws InterruptedException {
long start =System.currentTimeMillis();
int threadNum=10;
final CountDownLatch countDownLatch = new CountDownLatch(threadNum);
for(int i=0;i<threadNum;i++){
new Thread(new Runnable(){
@Override
public void run() {
for(int i=0;i<1000000;i++){
Object o = Singleton.getInstance();
//Object o =Singleton.INSTANCE;
}
countDownLatch.countDown();
}
}).start();
}
countDownLatch.await();
long end =System.currentTimeMillis();
System.out.println("总耗时:"+(end-start));
}
}