天天看點

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

繼續閱讀