单例模式

简单介绍

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

单例模式有以下特点: 

 1、单例类只能有一个实例。 

 2、单例类必须自己创建自己的唯一实例。 

 3、单例类必须给所有其他对象提供这一实例。 

 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。

一、懒汉式单例

package wbg;

import com.Thr;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {
    public static void main(String[] args) {
        ExecutorService ex= Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
           ex.execute(new Runnable() {
               @Override
               public void run() {
                   Boss boss=Boss.getInstance();
                   System.out.println(boss);
               }
           });

        }

    }
}
class Boss {
    private Boss(){};
    private  static  Boss boss=null;
    public static Boss getInstance() {
        if (boss == null) {
            boss = new Boss();
        }
        return boss;
    }
}
View Code

运行结果(多次运行)

Boos通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Boss的唯一实例只能通过getInstance()方法访问。

(事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在。)

以上懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Singleton实例,要实现线程安全,有以下三种方式,都是对getInstance这个方法改造,保证了懒汉式单例的线程安全

1、在getInstance方法上加同步

package wbg;

import com.Thr;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {
    public static void main(String[] args) {
        ExecutorService ex= Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
           ex.execute(new Runnable() {
               @Override
               public void run() {
                   Boss boss=Boss.getInstance();
                   System.out.println(boss);
               }
           });

        }

    }
}
class Boss {
    private Boss(){};
    private  static  Boss boss=null;
    public synchronized static Boss getInstance() {
        if (boss == null) {
            boss = new Boss();
        }
        return boss;
    }
}
View Code

运行结果

2、双重检查锁定

package wbg;

import com.Thr;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {
    public static void main(String[] args) {
        ExecutorService ex= Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
           ex.execute(new Runnable() {
               @Override
               public void run() {
                   Boss boss=Boss.getInstance();
                   System.out.println(boss);
               }
           });

        }

    }
}
class Boss {
    private Boss(){};
    private  static  Boss boss=null;
    public  static Boss getInstance() {
        if (boss == null) {
            synchronized(Boss.class){
                if (boss == null) {
                    boss = new Boss();
                }
            }
        }
        return boss;
    }
}
View Code

运行结果

3、静态内部类

package wbg;

import com.Thr;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {
    public static void main(String[] args) {
        ExecutorService ex= Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
           ex.execute(new Runnable() {
               @Override
               public void run() {
                   Boss boss=Boss.getInstance();
                   System.out.println(boss);
               }
           });

        }

    }
}
 class Boss {
    static class LazyHolder{
        private static final Boss inst=new Boss();
    }
    private Boss(){};
    public static final Boss getInstance(){
        return LazyHolder.inst;
    }
 }
View Code

运行结果

 这种比上面1、2都好一些,既实现了线程安全,又避免了同步带来的性能影响。

 详细:http://www.iteye.com/topic/652440

 

volatile关键字

package wbg;
public class Boss {
    String name;
    String sex;
    Float money;
    //初始化一个静态变量
    private  static volatile Boss boss=null;
    //设置为私有
    private  Boss() {
    }
    //构造一个静态方法,通过它初始化或返还对象
    public static Boss getBoss(){
        //双重检查所机制
        if(boss==null){
            synchronized(Boss.class){
                if(boss==null){
                    boss=new Boss();
                }
            }
        }
        return boss;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Float getMoney() {
        return money;
    }

    public void setMoney(Float money) {
        this.money = money;
    }
}

 

volatile关键字详细:http://www.cnblogs.com/dolphin0520/p/3920373.html

 

posted @ 2018-08-14 14:25  韦邦杠  阅读(517)  评论(0编辑  收藏  举报