1. 概念:
确保在一个JVM中一个类只有一个实例对象存在,这个类自已创建实例对象,并向整个系统提供此实例。
2. 单例实现:
(1)饿汉式单例:
view plain
package com.focus;
public class EagerSingleton {
/**
* 构造方法使用private修饰符修饰。
*/
private EagerSingleton() {
}
public static EagerSingleton getInstance() {
return mEagerSingleton;
}
private static EagerSingleton mEagerSingleton = new EagerSingleton();
}
(2)懒汉式单例:
view plain
package com.focus;
public class LazySingleton {
/**
* 构造方法使用private修饰符修饰。
*/
private LazySingleton() {
}
public static synchronized LazySingleton getInstance() {
if (mSingletonTwo == null) {
mSingletonTwo = new LazySingleton();
}
return mSingletonTwo;
}
private static LazySingleton mSingletonTwo = null;
}
(3)登记式单例:
view plain
package com.focus;
import java.util.HashMap;
import java.util.Map;
public class RegSingleton {
private static Map<String, RegSingleton> mRegSingletonMap = new HashMap<String, RegSingleton>();
static {
RegSingleton regSingleton = new RegSingleton();
mRegSingletonMap.put(regSingleton.getClass().getName(), regSingleton);
}
/**
* 构造方法用protected修饰符修饰。
*/
protected RegSingleton() {
}
public static RegSingleton getInstance(String singletonThreeName) {
if (singletonThreeName == null) {
singletonThreeName = "RegSingleton";
}
if (mRegSingletonMap.get(singletonThreeName) == null) {
try {
mRegSingletonMap.put(singletonThreeName, (RegSingleton) Class.forName(singletonThreeName).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return mRegSingletonMap.get(singletonThreeName);
}
}
3. 使用场景:
(1)系统配置文件,只需要加载一次,为各个模块提供配置信息,可以用单例实现,代码如下:
view plain
package com.focus;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class PropertyReader {
private static final String FILE_PATH = "*.properties";
private Properties mProperties = null;
private static PropertyReader mPropertyReader = new PropertyReader();
private PropertyReader() {
File file = new File(FILE_PATH);
if (file.exists()) {
mProperties = new Properties();
try {
mProperties.load(new FileInputStream(FILE_PATH));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public synchronized static PropertyReader getInstance() {
return mPropertyReader;
}
public final String getProperty(String key, String defaultValue) {
if (mProperties == null) {
throw new IllegalStateException();
}
return mProperties.getProperty(key, defaultValue);
}
/**
* 同步更新配置。
*/
public final synchronized void setProperty(String key, String value) {
try {
mProperties.setProperty(key, value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
(2)数据库连接池,为整个系统提供数据库连接,可以用单例实现:
A. Pool类实现:
view plain
package com.focus;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Pool {
/**
* 单例模式(Singleton模式),构造方法为私有的。
*/
private Pool() {
loadDriver(mDriverName);
createPool();
}
/**
* 装载和注册所有JDBC驱动程序。
*/
private void loadDriver(String driverName) {
if (driverName != null && ! "".equals(driverName)) {
try {
mDriver = (Driver) Class.forName(driverName).newInstance();
DriverManager.registerDriver(mDriver);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 创建连接池
*/
private void createPool() {
mDBConnectionPool = new DBConnectionPool(mDatabasePassword, mDatabaseURL, mDatabaseUserName, mNormalConnectNum, mMaxConnectNum);
if (mDBConnectionPool != null) {
System.out.println("创建连接池成功!");
} else {
System.out.println("创建连接池失败!");
}
}
/**
* 获取单例实例。
*/
public static synchronized Pool getInstance() {
if (mInstance == null) {
mInstance = new Pool();
}
return mInstance;
}
public Connection getConnection() {
if (mDBConnectionPool != null) {
return mDBConnectionPool.getConnection();
} else {
return null;
}
}
public Connection getConnection(long timeOut) {
if (mDBConnectionPool != null) {
return mDBConnectionPool.getConnection(timeOut);
}
return null;
}
public void releaseFreeConnection(Connection connection) {
if (mDBConnectionPool != null) {
mDBConnectionPool.releaseFreeConnection(connection);
}
}
/**
* 返回当前空闲连接数
*/
public int getnum() {
return mDBConnectionPool.getFreeConnectionNum();
}
/**
* 返回当前连接数
*/
public int getnumActive() {
return mDBConnectionPool.getCurrentConnectionNum();
}
/**
* 关闭所有连接,撤销驱动注册。
*/
public synchronized void release() {
/**
* 关闭连接
*/
mDBConnectionPool.release();
/**
* 撤销驱动
*/
try {
DriverManager.deregisterDriver(mDriver);
System.out.println("撤销JDBC驱动程序 " + mDriver.getClass().getName());
} catch (SQLException e) {
System.out.println("无法撤销JDBC驱动程序的注册:" + mDriver.getClass().getName());
}
}
private static Pool mInstance = null; // 定义唯一实例
private int mMaxConnectNum = 100;// 最大连接数
private int mNormalConnectNum = 10;// 保持连接数
private String mDatabasePassword = "";// 密码
private String mDatabaseURL = "jdbc:mysql://localhost/shop";// 连接URL
private String mDatabaseUserName = "root";// 用户名
private String mDriverName = "com.mysql.jdbc.Driver";// 驱动类
private Driver mDriver = null;// 驱动变量
private DBConnectionPool mDBConnectionPool = null;// 连接池实例变量
}
B.DatabaseConnectionPool类实现:
view plain
package com.focus;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Vector;
public class DBConnectionPool {
public DBConnectionPool(String databasePassWord, String databaseURL, String databaseUserName, int normalConnectionNum, int maxConnectionNum) {
mDatabasePassWord = databasePassWord;
mDatabaseURL = databaseURL;
mDatabaseUserName = databaseUserName;
mMaxConnectionNum = maxConnectionNum;
/* 初始normalConnectionNum个连接 */
for (int i = 0; i < normalConnectionNum; i++) {
Connection connection = createConnection();
if (connection != null) {
mFreeConnections.addElement(connection);
mFreeConnectionNum++;
}
}
}
/* 创建一个新连接 */
private Connection createConnection() {
Connection connection = null;
try {
if (mDatabaseUserName == null) {
connection = DriverManager.getConnection(mDatabaseURL);
} else {
connection = DriverManager.getConnection(mDatabaseURL, mDatabaseUserName, mDatabasePassWord);
}
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
/* 释放不用的连接到连接池 */
public synchronized void releaseFreeConnection(Connection con) {
mFreeConnections.addElement(con);
mFreeConnectionNum++;
mCheckedOut--;
mCurrentConnectionNum--;
notifyAll();
}
/* 返回当前空闲连接数 */
public int getFreeConnectionNum() {
return mFreeConnectionNum;
}
/* 返回当前连接数 */
public int getCurrentConnectionNum() {
return mCurrentConnectionNum;
}
// 获取一个可用连接
public synchronized Connection getConnection() {
Connection connection = null;
if (mFreeConnections.size() > 0) {
mFreeConnectionNum--;
connection = (Connection) mFreeConnections.firstElement();
mFreeConnections.removeElementAt(0);
try {
if (connection.isClosed()) {
System.out.println("从连接池删除一个无效连接!");
connection = getConnection();
}
} catch (SQLException e) {
System.out.println("从连接池删除一个无效连接!");
connection = getConnection();
}
} else if (mMaxConnectionNum == 0 || mCheckedOut < mMaxConnectionNum) { /* 没有空闲连接且当前连接小于最大允许值, 最大值为0则不限制 */
connection = createConnection();
}
if (connection != null) { /* 当前连接数加1 */
mCheckedOut++;
}
mCurrentConnectionNum++;
return connection;
}
/* 获取一个连接, 并加上等待时间限制, 时间为毫秒 */
public synchronized Connection getConnection(long timeout) {
long startTime = new Date().getTime();
Connection connection;
while ((connection = getConnection()) == null) {
try {
wait(timeout);
} catch (InterruptedException e) {
}
if ((new Date().getTime() - startTime) >= timeout) {
return null; /* 超时返回 */
}
}
return connection;
}
/* 关闭所有连接 */
public synchronized void release() {
Enumeration connections = mFreeConnections.elements();
while (connections.hasMoreElements()) {
Connection connection = (Connection) connections.nextElement();
try {
connection.close();
mFreeConnectionNum--;
} catch (SQLException e) {
e.printStackTrace();
}
}
mFreeConnections.removeAllElements();
mCurrentConnectionNum = 0;
}
private Vector<Connection> mFreeConnections = new Vector<Connection>();
private int mCheckedOut;
private int mMaxConnectionNum;
private String mDatabasePassWord;
private String mDatabaseURL;
private String mDatabaseUserName;
private static int mFreeConnectionNum = 0;/* 空闲的连接数 */
private static int mCurrentConnectionNum = 0;/* 当前的连接数 */
}