单例模式,最常见的就是饥饿模式,和懒汉模式,一个直接实例化对象一个调用方法时进行实例化对象。在多线程模式中,考虑到性能和线程安全问题。我们一般选择下面两种比较经典的单例模式,在性能提高的同时,又保证了线程安全。
饿汉式没有线程安全问题,懒汉式需要双重锁定解决可能的线程安全问题,下面是对懒汉模式实现线程安全的方法。
饿汉式的缺点是类一加载就实例化,提前占用系统资源
Doubble check instance 双重校验模式
Static inner class 静态内部加载类
静态内部加载模式示例:
使用内部类的好处是,静态内部类不会在单例加载时就加载,而是在调用getInstance()方法时才进行加载,达到了类似懒汉模式的效果,而这种方法又是线程安全的
package edu.sdut.queue;
//线程安全 public class InnerSingleton { private static class Singletion{ private static InnerSingleton single = new InnerSingleton(); } public static InnerSingleton getInstance() { return Singletion.single; } } |
双重校验模式示例:
/** * 双重校验模式,多线程打印出来的对象哈希值是一样的,说明是线程安全的单例模式 * @author Vision_TXG * */ public class DubbleSingleton { private static DubbleSingleton ds; public static DubbleSingleton getDe() { if(ds == null) { try { //模拟初始化对象的准备时间... Thread.sleep(3000); }catch(Exception e) { e.printStackTrace(); } synchronized(DubbleSingleton.class) { if(ds==null) { ds = new DubbleSingleton(); } } } return ds; } public static void main(String[] args) { Thread t1 = new Thread(new Runnable() {
@Override public void run() { // TODO Auto-generated method stub System.out.println(DubbleSingleton.getDe().hashCode()); } },"t1"); Thread t2 = new Thread(new Runnable() {
@Override public void run() { // TODO Auto-generated method stub System.out.println(DubbleSingleton.getDe().hashCode()); } },"t2"); t1.start(); t2.start(); } } |