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