1.什么是单例模式
注意:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
主要解决:一个全局使用的类频繁地创建与销毁。
何时使用:当您想控制实例数目,节省系统资源的时候。
如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。
关键代码:构造函数是私有的。
优点:
1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
2、避免对资源的多重占用(比如写文件操作)。
保证一个类只有一个实例。 为什么会有人想要控制一个类所拥有的实例数量? 最常见的原因是控制某些共享资源 (例如数据库或文件) 的访问权限。
它的运作方式是这样的: 如果你创建了一个对象, 同时过一会儿后你决定再创建一个新对象, 此时你会获得之前已创建的对象, 而不是一个新对象。
所有单例的实现都包含以下两个相同的步骤:
将默认构造函数设为私有, 防止其他对象使用单例类的 new运算符。
新建一个静态构建方法作为构造函数。 该函数会 “偷偷” 调用私有构造函数来创建对象, 并将其保存在一个静态成员变量中。 此后所有对于该函数的调用都将返回这一缓存对象。
在数据库连接池中应用单例模式这一概念,就是为了保证只有一个数据库实例被创建,每次我们即使创建不同的对象,也都是面向的是同一个数据库。
2.了解一下用到的mysql函数
(1) MySQL *mysql_init(MYSQL *mysql);
分配或初始化适合mysql_real_connect()的MYSQL对象。如果mysql是NULL指针,则该函数分配,初始化并返回新对象。否则,将初始化该对象并返回该对象的地址。如果mysql_init()分配了一个新对象,则在调用mysql_close()关闭连接时将释放该对象。
(2)MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag)
mysql_real_connect()尝试构建与在host上运行的 MySQL 服务器的连接。在执行需要有效MYSQL连接处理程序结构的任何其他 API 函数之前,Client 端程序必须成功连接到服务器。
对于第一个参数,请指定现有MYSQL结构的地址。在调用mysql_real_connect()之前,请调用mysql_init()初始化MYSQL结构。
host的值可以是主机名或 IP 地址。Client 端尝试如下连接:
如果host为NULL或字符串"localhost",则假定与 localhost 的连接:
如果port不为 0,则该值用作 TCP/IP 连接的端口号。请注意,host参数确定连接的类型。
如果unix_socket不是NULL,则字符串指定要使用的套接字或命名管道。请注意,host参数确定连接的类型。
client_flag的值通常为 0,但可以将其设置为以下标志的组合以启用某些功能:…
3.在这里面同样会用到信号量,锁等,所以是在上次锁机制的练习之后写的。
信号量是一个非负整数,就是可以使用的公共资源。
4.了解一下list这个数据结构
Lists将元素按顺序储存在链表中. 与 向量(vectors)相比, 它允许快速的插入和删除,但是随机访问却比较慢.
assign() 给list赋值
back() 返回最后一个元素
begin() 返回指向第一个元素的迭代器
clear() 删除所有元素
empty() 如果list是空的则返回true
end() 返回末尾的迭代器
erase() 删除一个元素
front() 返回第一个元素
get_allocator() 返回list的配置器
insert() 插入一个元素到list中
max_size() 返回list能容纳的最大元素数量
merge() 合并两个list
pop_back() 删除最后一个元素
pop_front() 删除第一个元素
push_back() 在list的末尾添加一个元素
push_front() 在list的头部添加一个元素
rbegin() 返回指向第一个元素的逆向迭代器
remove() 从list删除元素
remove_if() 按指定条件删除元素
rend() 指向list末尾的逆向迭代器
resize() 改变list的大小
reverse() 把list的元素倒转
size() 返回list中的元素个数
sort() 给list排序
splice() 合并两个list
swap() 交换两个list
unique() 删除list中重复的元素
在执行文件过程中出现一个bug 运行不出来
尝试了两种方法:
1.第一种换到root用户
2.使用改变权限命令
两种都失败了
最后发现不是这个问题,是我们要引入mysql的库函数,还有使用了锁机制,所以引入-pthread编译链接
#include <stdio.h>
#include <list>
#include <mysql/mysql.h>
#include <error.h>
#include <string.h>
#include <iostream>
#include <string>
#include <stdlib.h>
#include <pthread.h>
#include "./lock.h"
using namespace std;
class connection_pool
{
public:
MYSQL *GetConnection(); //获取数据库连接
bool ReleaseConnection(MYSQL *conn); //释放连接
int GetFreeConn(); //获取连接
void DestroyPool(); //销毁所有连接
//单例模式
static connection_pool *GetInstance();
void init(string url, string User, string PassWord, string DataBaseName, int Port, int MaxConn);
private:
connection_pool();
~connection_pool();
int m_MaxConn; //最大连接数
int m_CurConn; //当前已使用的连接数
int m_FreeConn; //当前空闲的连接数
locker lock;
list<MYSQL *> connList; //连接池
sem reserve;
public:
string m_url; //主机地址
string m_Port; //数据库端口号
string m_User; //登陆数据库用户名
string m_PassWord; //登陆数据库密码
string m_DatabaseName; //使用数据库名
};
connection_pool::connection_pool()
{
m_CurConn = 0;
m_FreeConn = 0;
}
connection_pool *connection_pool::GetInstance()
{
static connection_pool connPool;
return &connPool;
}
//构造初始化
void connection_pool::init(string url, string User, string PassWord, string DBName, int Port, int MaxConn)
{
m_url = url;
m_Port = Port;
m_User = User;
m_PassWord = PassWord;
m_DatabaseName = DBName;
for (int i = 0; i < MaxConn; i++)
{
MYSQL *con = NULL;
con = mysql_init(con);
if (con == NULL)
{
cout<<"MySQL Error!"<<endl;
exit(1);
}
else
{
cout<<"初始化成功"<<endl;
}
con = mysql_real_connect(con, url.c_str(), User.c_str(), PassWord.c_str(), DBName.c_str(), Port, NULL, 0);
if (con == NULL)
{
cout<<"MySQL Error!"<<endl;
exit(1);
}
else
{
cout<<"初始化成功"<<endl;
}
connList.push_back(con);
++m_FreeConn;
}
reserve = sem(m_FreeConn);
m_MaxConn = m_FreeConn;
}
//当有请求时,从数据库连接池中返回一个可用连接,更新使用和空闲连接数
MYSQL *connection_pool::GetConnection()
{
MYSQL *con = NULL;
if (0 == connList.size())
return NULL;
reserve.wait();
lock.lock();
con = connList.front();
connList.pop_front();
--m_FreeConn;
++m_CurConn;
lock.unlock();
return con;
}
//释放当前使用的连接
bool connection_pool::ReleaseConnection(MYSQL *con)
{
if (NULL == con)
return false;
lock.lock();
connList.push_back(con);
++m_FreeConn;
--m_CurConn;
lock.unlock();
reserve.post();
return true;
}
//销毁数据库连接池
void connection_pool::DestroyPool()
{
lock.lock();
if (connList.size() > 0)
{
list<MYSQL *>::iterator it;
for (it = connList.begin(); it != connList.end(); ++it)
{
MYSQL *con = *it;
mysql_close(con);
}
m_CurConn = 0;
m_FreeConn = 0;
connList.clear();
}
lock.unlock();
}
//当前空闲的连接数
int connection_pool::GetFreeConn()
{
return this->m_FreeConn;
}
connection_pool::~connection_pool()
{
DestroyPool();
}
int main()
{
string user = "root";
string passwd = "root";
string databasename = "WebServer";
connection_pool *m_connPool;
//初始化数据库连接池
m_connPool = connection_pool::GetInstance();
m_connPool->init("localhost", user, passwd, databasename, 3306, 5);
MYSQL *con;
con=m_connPool->GetConnection();
cout<<m_connPool->GetFreeConn()<<endl;
bool res=m_connPool->ReleaseConnection(con);
if(res)
{
cout<<"释放成功"<<endl;
}
else
{
cout<<"释放失败"<<endl;
}
m_connPool->DestroyPool();
return 0;
}
哈哈哈 老娘终于运行成功了。
在运行成功的过程中出现了很多错误。
最后反正就是要把你下载的mysql库函数指出来,还有需要用到的库函数连接,然后编译。
这用到的锁机制还是前面那个lock.h文件夹,在上一遍吧。
虽然运行成功,明显我的数据库是连接不上的,我再去瞅瞅。
相应的数据库WebServer和port都是对应的。
然后我数据对以后,终于成功了!
#include <iostream>
#include <exception>
#include <pthread.h>
#include <semaphore.h>
class sem
{
public:
sem()
{
if (sem_init(&m_sem, 0, 0) != 0)
{
throw std::exception();
}
}
sem(int num)
{
if (sem_init(&m_sem, 0, num) != 0)
{
throw std::exception();
}
}
~sem()
{
sem_destroy(&m_sem);
}
bool wait()
{
return sem_wait(&m_sem) == 0;
}
bool post()
{
return sem_post(&m_sem) == 0;
}
private:
sem_t m_sem;
};
class locker
{
public:
locker()
{
if (pthread_mutex_init(&m_mutex, NULL) != 0)
{
throw std::exception();
}
}
~locker()
{
pthread_mutex_destroy(&m_mutex);
}
bool lock()
{
return pthread_mutex_lock(&m_mutex) == 0;
}
bool unlock()
{
return pthread_mutex_unlock(&m_mutex) == 0;
}
pthread_mutex_t *get()
{
return &m_mutex;
}
private:
pthread_mutex_t m_mutex;
};
class cond
{
public:
cond()
{
if (pthread_cond_init(&m_cond, NULL) != 0)
{
//pthread_mutex_destroy(&m_mutex);
throw std::exception();
}
}
~cond()
{
pthread_cond_destroy(&m_cond);
}
bool wait(pthread_mutex_t *m_mutex)
{
int ret = 0;
//pthread_mutex_lock(&m_mutex);
ret = pthread_cond_wait(&m_cond, m_mutex);
//pthread_mutex_unlock(&m_mutex);
return ret == 0;
}
bool timewait(pthread_mutex_t *m_mutex, struct timespec t)
{
int ret = 0;
//pthread_mutex_lock(&m_mutex);
ret = pthread_cond_timedwait(&m_cond, m_mutex, &t);
//pthread_mutex_unlock(&m_mutex);
return ret == 0;
}
bool signal()
{
return pthread_cond_signal(&m_cond) == 0;
}
bool broadcast()
{
return pthread_cond_broadcast(&m_cond) == 0;
}
private:
//static pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
};