單例模式指的是一個類只會有一個實例,即是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,再創建一個,導致存在多個單例實例的情況;