對於單例模式的理解


  單例模式指的是一個類只會有一個實例,即是instance,java web中Servlet就是單實例多線程的,單實例運用場景很多,例如在計算機系統中,線程池、緩存、日志對象、對話框、打印機、顯卡的驅動程序對象常被設計成單例,單例的好處:節省內存,不需要new出來那么多實例;配合線程同步;單例一般用於公共資源;

  舉個例子:網頁點擊量通常設置成單例模式,一個靜態全局變量用來計數,單例模式用於控制這個全局變量的訪問,用同步鎖住計數器來計數;

  單例模式主要有3個特點,:
1、單例類確保自己只有一個實例(構造方法私有化)

2、單例類必須自己創建自己的實例。
3、單例類必須為其他對象提供唯一的實例。
public class Singleton {
    private Singleton() {}
    private static Singleton single=null;
    //靜態工廠方法
    public static Singleton getInstance() {
         if (single == null) { 
             single = new Singleton();
         } 
        return single;
    }

舉個工程中單例多線程的例子:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ibm.ecif.framework.db.DataSource;

/**
 * 配置管理,主要對模擬交易模塊的模擬文件名的管理
 *
 * @author djw
 * @version 1.0 2014-10-26
 */

public class DBConfigManager {

    private static Logger log = LoggerFactory.getLogger(DBConfigManager.class);
    private static Timestamp  cts = null;

    // Singleton implementation function.
    private static DBConfigManager theInstance = null;

    // Config file properties
    private Map<String, String> theProperties = new HashMap<String, String>();

    /**
     * Default Constructer
     */
    private DBConfigManager() {
        super();
    } /* ConfigManager() */

    /**
     * Return the reference instance of the config manager Use this in
     * preference to the singleton APIs.
     *
     * @return an instance of ConfigManager
     */
    public static synchronized DBConfigManager getInstance() {
        if (theInstance == null) {
            theInstance = new DBConfigManager();
            theInstance.init();
        }

        return theInstance;
    } /* getInstance() */

    public void init() {

        // theInstance.theProperties.clear();

        Connection conn = null;
        // int m = 0;
        // int m2 = 0;
        // try {
        // m = JedisConfigMgr.hlen(Framework.getJedisNS() +
        // CacheCode.PARTY_IDFY_HASHCODE);
        // m2 = JedisConfigMgr.hlen(Framework.getJedisNS() +
        // CacheCode.CUST_NUM);
        // } catch (RuntimeException e) {
        // return;
        // }
        // if (m>0||m2>0) {
        // return;
        // }
        //
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {

            // 初始化CUST_NUM緩存
            conn = DataSource.getConnection();
            String sql = "select key, value from TB9005";
            stmt = conn.prepareStatement(sql);
            rs = stmt.executeQuery();

            Map<String, String> map = new HashMap<String, String>();
            while (rs.next()) {
                String key = rs.getString("key").trim();
                String value = rs.getString("value").trim();
                map.put(key, value);
            }
            theProperties = map;
        } catch (SQLException e) {
            log.error("[ErrorCodeDAO getMap]getErrorcodeMap error!", e);
        } finally {
            DataSource.closeRs(rs);
            DataSource.closeStatement(stmt);
            try {
                if (conn != null) {
                    conn.commit();
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
            DataSource.closeConnection(conn);
        }
       
        //Other init
        cts=null;
    }

    /**
     * get the Config Value
     *
     * @param key
     *            Config_key
     * @return Config_value
     */
    public String getConfigValue(String key) {
        if (theProperties == null) {
            return null;
        }
        return theProperties.get(key);
    }

    /**
     * get the Config Value, if not exists then return the default value
     *
     * @param key
     *            Config_key
     * @param defaultValue
     *            default_Value
     * @return Config_value or default_Value
     */
    public String getConfigValue(String key, String defaultValue) {
        if (theProperties == null || theProperties.get(key) == null) {
            return defaultValue;
        }
        return theProperties.get(key);
    }

    public Timestamp getCreateTime() {
        if (theProperties != null && cts == null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String timeStr = theProperties.get("ECIF_ACTIVE_TIME");
            if (timeStr != null) {
                try {
                    cts = new Timestamp(sdf.parse(timeStr).getTime());
                } catch (ParseException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
        return cts;
    }
}

 將getInstance方法synchronized,避免發生一個線程過來發現instance為null,創建一個,另一個線程過來還發現instance為null,再創建一個,導致存在多個單例實例的情況;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM