天天看点

23种设计模式之(单例模式案例)

一、设计模式 (Design Patterns)分类

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

二、单例模式

特征:一个类只有一个实例对象。(举例:你,可以扮演儿子,丈夫,爸爸,员工,但是世界上只有一个你,这就是单例。)

三、简单案例

单例模式主要存在两种: 饿汉式 ,懒汉式

 饿汉式代码  案例:

public final class Singleton {
	private static final Singleton instance = new Singleton ();
	private Singleton(){
		//do something
	}
	public static Singleton getInstance(){
		return instance;
	}
}
           

懒汉式代码 案例(两种写法):

第一种:线程安全

public final class Singleton {
	private volatile static Singleton intance=null;
	private static Object INSTANCE_LOCKER = new Object();;
	private Singleton(){
		//do something
	}
	public static Singleton getSingleton(){
		if(null==intance){
			synchronized(INSTANCE_LOCKER){
				if(null==intance){
					intance = new Singleton();
				}
			}
		}
		return intance;
	}	
}
           

第二种:(静态内部类)

     利用了classloder的机制来保证初始化instance时只有一个线程。显示调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。

public final class Singleton {
	private static class SingletonHolder{
		private static final Singleton INSTANCE= new Singleton ();
		private SingletonHolder(){
			
		}
	}
	private Singleton(){
		//do something
	}
	public static Singleton getInstance(){
		return SingletonHolder.INSTANCE;
	}
}
           

注意:final

     当final修饰一个类时,表明这个类不能被继承。

     当final修饰一个方法时,第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。

     当final修饰一个变量时,对其初始化之后便不能再让其指向另一个对象。(但是初始化对象的内部引用可以)。

四、案例场景

作用:资源共享,控制资源。

资源共享:读取配置文件,缓存单例工厂,多个线程共同计数。

控制资源:线程池的管理。

案例一:

读取配置文件:

/**
 * 单例实例1
 * 懒加载,懒汉式
 * 案例:加载配置文件中的配置对象
 *
 *
 */
public class ConfigHelper {
	//1.日志属性
    //2.RemoteTransportServer核心属性对象
    //List和Map相关容器,解析的配置对象
    private static class LazyHolder
    {
        private static final ConfigHelper INSTANCE = new ConfigHelper();
        private LazyHolder()
        {
        }
    }
    
	private ConfigHelper(){
		//3.加载配置文件,解析配置文件为一个对象
		//do something ,解析xml文件
		init();
	}
	
	private void init(){
		//4.实例化配置文件的中的对象,并做一些初始化工作
		//do something ,根据xml配置,对类做一些初始化工作
	}
	
	//5.返回单例实例
    public static final ConfigHelper getInstance()
    {
        return LazyHolder.INSTANCE;
    }
    
    //6.更新配置文件的内容
    public void updateConfig(String server){
    	//1.Clear掉Map.clear(),Object=null; 
    	//2.重新像构造方法中一样读取配置文件。
    	//do something ,重新解析xml文件
    	//3.初始化init()
    	init();
    }
}
           

统一解析xml的工具框架

public class XMLHelper {
	 static 
	 {
	        isInit = Boolean.FALSE;
	        isCacheInit = Boolean.FALSE;
	 }
	 
     private static Boolean isInit;
     private static Boolean isCacheInit;
     private static XMLHelper instance = null;
     private static Defaults defaults  = null;
     private static Caches caches  = null;

	 private XMLHelper()
	 {
	 }
	 public static XMLHelper getInstance()throws Exception
	 {
	        if(isInit.equals(Boolean.FALSE))
	        {
	            synchronized(isInit)
	            {
	                if(isInit.equals(Boolean.FALSE))
	                {
	                	//主要的配置文件
	                    defaults = createDefaults();
	                    isInit = Boolean.TRUE;
	                }
	            }
	            instance = new XMLHelper();
	        }
	        return instance;
	 }
	 public Defaults getDefaults(){
		 return defaults;
	 }
	 
     public Caches getCaches()
     {
        if(caches == null)
            synchronized(isCacheInit)
            {
                if(isCacheInit.equals(Boolean.FALSE))
                    try
                    {
                        caches = createCaches();
                        isCacheInit = Boolean.TRUE;
                    }
                    catch(Throwable ex)
                    {
                        throw new RuntimeException(ex);
                    }
            }
        return caches;
     }
     
     private static Defaults createDefaults(){
    	 //读取配置文件
    	 return null;
     }
     private static Caches createCaches(){
    	 //读取配置文件
    	 return null;
     }
}
           

案例二、

线程池

package com.cn.javaFrame.demo.demo02.threadpool;

import java.util.LinkedList;
import java.util.List;
/**
 * 线程池类,线程管理器:创建线程,执行任务,销毁线程,获取线程基本信息
 * @author 
 *
 */
public final class ThreadPool {
	//线程池中默认线程的个数为5
	private static int worker_num = 5;
	//工作线程
	private WorkThread[] workThreads;
	//未处理的任务
	private static volatile int finished_task = 0;
	//任务列表,作为一个缓存,List线程不安全
	private List<Runnable> taskQueue = new LinkedList<Runnable>();
	private static ThreadPool threadPool;
	
	private ThreadPool(){
		this(5);
	}
	private ThreadPool(int work_num){
		ThreadPool.worker_num=work_num;
		workThreads = new WorkThread[worker_num];
		for(int i=0; i<work_num; i++){
			workThreads[i] = new WorkThread();
			//开启线程池
			workThreads[i].start();
		}
	}
	public static ThreadPool getThreadPool(){
		return getTheadPool(ThreadPool.worker_num);
	}
	
	public static ThreadPool getTheadPool(int worker_num1){
		if(worker_num1<=0){
			worker_num1=ThreadPool.worker_num;
		}
		if(threadPool == null){
			threadPool = new ThreadPool(worker_num1);
		}
		return threadPool;
	}
	// 执行任务,其实只是把任务加入任务队列,什么时候执行有线程池管理决定
    public void execute(Runnable task) {  
        synchronized (taskQueue) {  
            taskQueue.add(task);  
            taskQueue.notify();  
        }  
    }  
    // 批量执行任务,其实只是把任务加入任务队列,什么时候执行有线程池管理器决定 
    public void execute(Runnable[] task) {  
        synchronized (taskQueue) {  
            for (Runnable t : task)  
                taskQueue.add(t);  
            taskQueue.notify();  
        }  
    }  
  
    // 批量执行任务,其实只是把任务加入任务队列,什么时候执行有线程池管理器决定 
    public void execute(List<Runnable> task) {  
        synchronized (taskQueue) {  
            for (Runnable t : task)  
                taskQueue.add(t);  
            taskQueue.notify();  
        }  
    } 

    // 销毁线程池,该方法保证在所有任务都完成的情况下才销毁所有线程,否则等待任务完成才销毁  
    public void destroy() {  
        while (!taskQueue.isEmpty()) {// 如果还有任务没执行完成,就先睡会吧  
            try {  
                Thread.sleep(10);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  
        // 工作线程停止工作,且置为null  
        for (int i = 0; i < worker_num; i++) {  
        	workThreads[i].stopWorker();  
        	workThreads[i] = null;  
        }  
        threadPool=null;  
        taskQueue.clear();// 清空任务队列  
    } 
    
    // 返回工作线程的个数  
    public int getWorkThreadNumber() {  
        return worker_num;  
    }  
    
    // 返回已完成任务的个数,这里的已完成是只出了任务队列的任务个数,可能该任务并没有实际执行完成  
    public int getFinishedTasknumber() {  
        return finished_task;  
    }  
    
    // 返回任务队列的长度,即还没处理的任务个数  
    public int getWaitTasknumber() {  
        return taskQueue.size();  
    } 
    
    // 覆盖toString方法,返回线程池信息:工作线程个数和已完成任务个数  
    @Override  
    public String toString() {  
        return "WorkThread number:" + worker_num + "  finished task number:"  
                + finished_task + "  wait task number:" + getWaitTasknumber();  
    }  
    
    
    /** 
     * 内部类,工作线程 
     */  
    private class WorkThread extends Thread {  
        // 该工作线程是否有效,用于结束该工作线程  
        private boolean isRunning = true;  
  
        /* 
         * 关键所在啊,如果任务队列不空,则取出任务执行,若任务队列空,则等待 
         */  
        @Override  
        public void run() {  
            Runnable r = null;  
            while (isRunning) {// 注意,若线程无效则自然结束run方法,该线程就没用了  
                synchronized (taskQueue) {  
                    while (isRunning && taskQueue.isEmpty()) {// 队列为空  
                        try {  
                            taskQueue.wait(20);  
                        } catch (InterruptedException e) {  
                            e.printStackTrace();  
                        }  
                    }  
                    if (!taskQueue.isEmpty())  
                        r = taskQueue.remove(0);// 取出任务  
                }  
                if (r != null) {  
                    r.run();// 执行任务  
                }  
                finished_task++;  
                r = null;  
            }  
        }  
  
        // 停止工作,让该线程自然执行完run方法,自然结束  
        public void stopWorker() {  
            isRunning = false;  
        }  
    } 
}
           

线程池出处:

http://blog.csdn.net/hsuxu/article/details/8985931

继续阅读