单例模式
package com.seven.exercise.testEception;
/**
* 单例模式,饿汉式
* @author Seven
*
*/
public class SingleDemoHunger {
private SingleDemoHunger() {
}
private static SingleDemoHunger sdh = new SingleDemoHunger();
public static SingleDemoHunger getInstance() {
return sdh;
}
}
package com.seven.exercise.testEception;
/**
* 懒汉式
* @author Seven
*
*/
public class SingleDemo {
/**
* 私有化构造函数
*/
private SingleDemo(){
}
private static SingleDemo singleDemo = null;
/**
* 提供获取实例的方法
* @return
*/
public static SingleDemo getInstance(){
if(singleDemo==null){
singleDemo = new SingleDemo();
}
return singleDemo;
}
}
饿汉式属于立即加载,所以不存在在多线程中出现错误的情况;
但是懒汉式的话就有可能出现问题了,如多一个线程执行到判断是否为空的语句
if(singleDemo==null)
的时候,当前线程被阻塞,而第二个线程进来了,这样的话第二个线程创建了新的对象,那么第一个线程被唤醒的时候又创建多一个对象,这样在内存中就存在了两个对象,明显和单例设计模式不符,那么我们应该怎么做呢?
很简单,用 synchronized关键字就可以轻松解决:package com.seven.exercise.testEception;
/**
* 懒汉式
* @author Seven
*
*/
public class SingleDemo {
/**
* 私有化构造函数
*/
private SingleDemo(){
}
private static SingleDemo singleDemo = null;
/**
* 提供获取实例的方法,用synchronized来解决多线程的问题.C++ 使用 lock() 和unlock()来实现
* @return
*/
public static SingleDemo getInstance(){
synchronized (SingleDemo.class) {
if(singleDemo==null){
singleDemo = new SingleDemo();
}
}
return singleDemo;
}
}
这样就减少了创建多个实例的可能,但是还是存在创建多个实例的可能性,而且同步锁肯定要消耗资源,这样的话就会降低效率,那么有什么办法可以提高效率呢?答案是有的,那就是通过二次判断,这样的话就不用每次都执行同步代码块,这样的话,只需第一次执行的时候比较占资源,以后的话就和之前的一样了:
package com.seven.exercise.testEception;
/**
* 懒汉式
* @author Seven
*
*/
public class SingleDemo {
/**
* 私有化构造函数
*/
private SingleDemo(){
}
private static SingleDemo singleDemo = null;
/**
* 提供获取实例的方法,用synchronized来解决多线程的问题.
* @return
*/
public static SingleDemo getInstance(){
//二次判断提高效率
if(singleDemo==null){
synchronized (SingleDemo.class) {
if(singleDemo==null){
singleDemo = new SingleDemo();
}
}
}
return singleDemo;
}
}
设计模式中的单例模式的代码为什么析构函数会多次被调用,而构造函数只调用一次
********************************************************************
created: 2006/07/20
filename: Singleton.h
author: 李创
http://www.cppblog.com/converse/
purpose: Singleton模式的演示代码
*********************************************************************/
#ifndef SINGLETON_H
#define SINGLETON_H
class Singleton
{
public:
Singleton();
~Singleton();
// 静态成员函数,提供全局访问的接口
static Singleton* GetInstancePtr();
static Singleton GetInstance();
void Test();
private:
// 静态成员变量,提供全局惟一的一个实例
static Singleton* m_pStatic;
};
#endif
/********************************************************************
created: 2006/07/20
filename: Singleton.cpp
author: 李创
http://www.cppblog.com/converse/
purpose: Singleton模式的演示代码
*********************************************************************/
#include "Singleton.h"
#include <iostream>
// 类的静态成员变量要在类体外进行定义
Singleton* Singleton::m_pStatic = NULL;
Singleton::Singleton()
{
std::cout << "构造函数被调用/n";
}
Singleton::~Singleton()
{
std::cout << "析构函数被调用/n";
}
Singleton* Singleton::GetInstancePtr()
{
if (NULL == m_pStatic)
{
m_pStatic = new Singleton();
}
return m_pStatic;
}
Singleton Singleton::GetInstance()
{
return *GetInstancePtr();
}
void Singleton::Test()
{
std::cout << "Test函数被调用!/n";
}
/********************************************************************
created: 2006/07/20
filename: Main.cpp
author: 李创
http://www.cppblog.com/converse/
purpose: Singleton模式的测试代码
*********************************************************************/
#include "Singleton.h"
#include <stdlib.h>
//析构函数只被调用一次的情形:
int main()
{
// 不用初始化类对象就可以访问了
for( int i =0; i < 10; i++)
{
Singleton::GetInstancePtr()->Test();//程序执行完这一句之后析构函数被调用一次,如果是第一次,构造函数被调用
//并且构造函数只被调用一次
}
return 0;
}
程序运行结果:
构造函数被调用
Test函数被调用!
Test函数被调用!
Test函数被调用!
Test函数被调用!
Test函数被调用!
Test函数被调用!
Test函数被调用!
Test函数被调用!
Test函数被调用!
Test函数被调用!
析构函数多次被调用的情况:
void Test();
int g_iTest = 0;
int main()
{
for( int i = 0; i < 5; i++ )//析构函数5次被调用
{
Test();
}
system("pause");
return 0;
}
void Test()
{
g_iTest++;
printf( "第 %d 次调用成员函数", g_iTest );
Singleton::GetInstance().Test();
printf( "/n/n" );
}
第 1 次调用成员函数(构造函数被调用)Test!
(析构函数被调用)
第 2 次调用成员函数Test!
(析构函数被调用)
第 3 次调用成员函数Test!
(析构函数被调用)
第 4 次调用成员函数Test!
(析构函数被调用)
第 5 次调用成员函数Test!
(析构函数被调用)
请按任意键继续. . .