Java 单例设计模式

来源:互联网 发布:swisse淘宝旗舰店假货 编辑:程序博客网 时间:2024/04/29 17:54

单例模式,顾名思义就是确保一个类只有一个实例。单例模式英文原话“Ensure a class has only one instance,and provide a global point of access to it.”翻译,单例模式是确保一个类只有一个实例,而且自行实例化并向这个系统提供这个实例。单例模式通常分三种:饿汉式单例类、懒汉式单例类和登记式单例类。下面说说前两种单例类。

饿汉式单例类是在类加载时,进行对象实例化;懒汉式单例类是在第一次引用该类时进行对象实例化。

饿汉式单例类代码如下所示:

public class Singleton{private static Singleton _instance = new Singleton();//构造方法私有,保证外界不能直接实例化;private Singleton(){}//通过该方法获得实例对象;public static getInstance(){return _instance;}}

懒汉式单例类代码如下所示:

public class Singleton{private static Singleton _instance =null;//构造方法私有,保证外界不能直接实例化;private Singleton(){}//通过该方法获得实例对象,此时应该同步,防止多个线程同时调用该方法而创建多个实例;public static synchronized getInstance(){if(_instance==null){_instance = new Singleton();}return _instance}}
以上代码片段可以看出饿汉式单例类和懒汉式单例类的差别。需要注意的是,懒汉式单例获得实例的方法需要同步,饿汉式不必同步,因为实例在类加载时已经创建了,即使多个线程同时调用该方法获得还是同个实例;单例类的构造方法都是私有的。下面写一个多线程访问单列类的demo,demo中使用的是饿汉式单例类,其实Java语言更适合使用饿汉式单例类。下面上代码。

单例类如下:

//单例类,该单例类实现一个计数功能;public class NumController {private static NumController nController = new NumController();private int num = 0;//单例类的构造函数是private的,只供自己调用;private NumController(){}//向调用者提供单例对象;public static  NumController getInstance(){return nController;}//计数器加1,注意要同步;public synchronized int getNum(){return num++;}}

下面是主函数类:

public class SingletonPatternTest {/** * @param args */public static void main(String[] args) {//创建两个访问单例类的线程,由于线程是用内部类实现,所以需要先创建一个外围对象;SingletonPatternTest spt = new SingletonPatternTest();//将单例类对象传递给线程;Thread threadOne = spt.new ThreadOne(NumController.getInstance());Thread threadTwo = spt.new ThreadTwo(NumController.getInstance());//开启线程threadOne.start();threadTwo.start();}class ThreadOne extends Thread{NumController nController;public ThreadOne(){}public ThreadOne(NumController nController){this.nController=nController;}public void run(){for(int i=0;i<5;i++){System.out.println("这是ThreadOne第"+nController.getNum()+"次访问NumController");try {Thread.sleep(200);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}class ThreadTwo extends Thread{NumController nController;public ThreadTwo(){}public ThreadTwo(NumController nController){this.nController=nController;}public void run(){for(int i=0;i<5;i++){System.out.println("这是ThreadTwo第"+nController.getNum()+"次访问NumController");try {Thread.sleep(200);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}

运行结果如下:

这是ThreadOne第0次访问NumController
这是ThreadTwo第1次访问NumController
这是ThreadTwo第2次访问NumController
这是ThreadOne第3次访问NumController
这是ThreadOne第4次访问NumController
这是ThreadTwo第5次访问NumController
这是ThreadOne第6次访问NumController
这是ThreadTwo第7次访问NumController
这是ThreadOne第8次访问NumController
这是ThreadTwo第9次访问NumController