对于单例模式的理解

  单例模式指的是一个类只会有一个实例,即是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,再创建一个,导致存在多个单例实例的情况;

原文地址:https://www.cnblogs.com/jianwei-dai/p/5729623.html