当前位置:网站首页>Implementing singleton mode of database under QT multithreading
Implementing singleton mode of database under QT multithreading
2022-06-12 13:33:00 【You stole my name】
One 、singleton Model is introduced
singleton Patterns can define unique objects for a class , And access this object through a static member function . A simpler approach is to define the object of this class as a static local object in a function , Then let the function return the address of the object .
Two 、 Use QAtomicPointer Implementation of multi-threaded database operation
I posted the code directly , I don't want to talk about the principle . You can see it directly , Also post the test code
The header file :connectionpool.h
#ifndef CONNECTIONPOOL_H
#define CONNECTIONPOOL_H
#include <QtSql>
#include <QQueue>
#include <QString>
#include <QMutex>
#include <QMutexLocker>
#include<QAtomicPointer>
class ConnectionPool {
public:
static void release(); // Close all database connections
static QSqlDatabase openConnection(); // Get database connection
static void closeConnection(QSqlDatabase connection); // Release the database connection back to the connection pool
~ConnectionPool();
static ConnectionPool& getInstance();// Singleton initialization
public:
QSqlDatabase createConnection(const QString &connectionName); // Create database connection
QQueue<QString> usedConnectionNames; // Used database connection name
QQueue<QString> unusedConnectionNames; // Unused database connection name
// database information
QString hostName;
QString databaseName;
QString username;
QString password;
QString databaseType;
int port;
bool testOnBorrow; // Verify whether the connection is valid when obtaining the connection
QString testOnBorrowSql; // Test access to the database SQL
int maxWaitTime; // Get connection maximum wait time
int waitInterval; // Wait interval while trying to get a connection
int maxConnectionCount; // maximum connection
private:
ConnectionPool();
ConnectionPool(const ConnectionPool &other);
ConnectionPool& operator=(const ConnectionPool &other);
static QMutex mutex;
static QWaitCondition waitConnection;
static QAtomicPointer<ConnectionPool> m_instance;
};
#endif // CONNECTIONPOOL_H
Source file :connectionpool.cpp
#include "connectionpool.h"
#include <QDebug>
QMutex ConnectionPool::mutex;
QAtomicPointer<ConnectionPool> ConnectionPool::m_instance=nullptr;
QWaitCondition ConnectionPool::waitConnection;
ConnectionPool::ConnectionPool() {
// The information about creating a database connection needs to be obtained by reading the configuration file during actual development ,
// For the convenience of demonstration, it is written in the code .
// QString str=QDir::currentPath()+"/Profile/config.ini";
//QSettings setting(str, QSettings::IniFormat);// read configuration file Do not write clear path , Generally, it is at the relative path
// setting.beginGroup("DataBaseServer");
//QString IP = setting.value("IP").toString();
// QString DataBase = setting.value("DataBase").toString();
//QString UserName = setting.value("UserName").toString();
//QString PassWord = setting.value("PassWord").toString();
// int Port=setting.value("Port").toInt();
// hostName = IP;
//port=Port;
databaseName = "tset.db";
//username = UserName;
// password = PassWord;
databaseType = "QSQLITE";
testOnBorrow = true;
testOnBorrowSql = "SELECT 1";
maxWaitTime = 1000;
waitInterval = 200;
maxConnectionCount = 5;
}
ConnectionPool::~ConnectionPool() {
// Delete all connections when destroying the connection pool
foreach(QString connectionName, usedConnectionNames) {
QSqlDatabase::removeDatabase(connectionName);
}
foreach(QString connectionName, unusedConnectionNames) {
QSqlDatabase::removeDatabase(connectionName);
}
}
ConnectionPool& ConnectionPool::getInstance()
{
// if (nullptr == instance)
// {
// QMutexLocker locker(&mutex);
// if (nullptr == instance)
// {
// instance = new ConnectionPool();
// }
// }
// return *instance;
#ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
if(!QAtomicPointer<ConnectionPool>::isTestAndSetNative())
qDebug()<<"Error: TestAndSetNative not supported!";
#endif
{
QMutexLocker locker(&mutex);
if(m_instance.testAndSetOrdered(nullptr,nullptr))
{
m_instance.testAndSetOrdered(nullptr,new ConnectionPool);
}
return *m_instance.load();
}
}
void ConnectionPool::release() {
QMutexLocker locker(&mutex);
delete m_instance;
m_instance = nullptr;
}
QSqlDatabase ConnectionPool::openConnection() {
ConnectionPool& pool = ConnectionPool::getInstance();
QString connectionName;
QMutexLocker locker(&mutex);
// Number of connections created
int connectionCount = pool.unusedConnectionNames.size() + pool.usedConnectionNames.size();
// If the connection has run out , wait for waitInterval Milliseconds to see if there is a connection available , The longest wait maxWaitTime millisecond
for (int i = 0;
i < pool.maxWaitTime
&& pool.unusedConnectionNames.size() == 0 && connectionCount == pool.maxConnectionCount;
i += pool.waitInterval) {
waitConnection.wait(&mutex, pool.waitInterval);
// Recalculate the number of connections created
connectionCount = pool.unusedConnectionNames.size() + pool.usedConnectionNames.size();
}
if (pool.unusedConnectionNames.size() > 0)
{
// There are recycled connections , Reuse them
connectionName = pool.unusedConnectionNames.dequeue();
} else if (connectionCount < pool.maxConnectionCount) {
// No connections have been recycled , But the maximum number of connections is not reached , Create a new connection
connectionName = QString("Connection-%1").arg(connectionCount + 1);
} else {
// The maximum number of connections has been reached
//qDebug() << "Cannot create more connections.";
return QSqlDatabase();
}
// Create connection
QSqlDatabase db = pool.createConnection(connectionName);
// Only valid connections are put into usedConnectionNames
if (db.isOpen()) {
pool.usedConnectionNames.enqueue(connectionName);
}
return db;
}
void ConnectionPool::closeConnection(QSqlDatabase connection) {
ConnectionPool& pool = ConnectionPool::getInstance();
QString connectionName = connection.connectionName();
// If the connection we created , from used In the delete , Put in unused in
if (pool.usedConnectionNames.contains(connectionName)) {
QMutexLocker locker(&mutex);
pool.usedConnectionNames.removeOne(connectionName);
pool.unusedConnectionNames.enqueue(connectionName);
waitConnection.wakeOne();
}
}
QSqlDatabase ConnectionPool::createConnection(const QString &connectionName)
{
// The connection has been created , Reuse it , Instead of recreating
if (QSqlDatabase::contains(connectionName))
{
QSqlDatabase db1 = QSqlDatabase::database(connectionName);
if (testOnBorrow) {
// Back to accessing the database before connecting , If the connection breaks , reestablish connection
//qDebug() << "Test connection on borrow, execute:" << testOnBorrowSql << ", for" << connectionName;
QSqlQuery query(testOnBorrowSql, db1);
if (query.lastError().type() != QSqlError::NoError && !db1.open()) {
// qDebug() << "Open datatabase error:" << db1.lastError().text();
return QSqlDatabase();
}
}
return db1;
}
// Create a new connection
QSqlDatabase db = QSqlDatabase::addDatabase(databaseType, connectionName);
// db.setHostName(hostName);
db.setDatabaseName(databaseName);
// db.setUserName(username);
// db.setPassword(password);
//db.setPort(port);
if (!db.open()) {
qDebug() << "Open datatabase error:" << db.lastError().text();
return QSqlDatabase();
}
return db;
}
Test introduction : use Qtconcurrent Module map() function .map Function has two arguments ,Sequence &sequence, and MapFunctor function.sequence by QList type ,function For the function , Its parameter is sequence Get member .map The function will automatically open up the corresponding sequence The number of temporary threads .
sequence:
QStringList list;
list.append("ui");
list.append("fhjd");
list.append("vkdll");
function:
void getsqlData(QString name)
{
time_t begin,end;
begin=clock();
QSqlDatabase db= ConnectionPool::openConnection();
QSqlQuery sql_query(db);
sql_query.exec("select * from student");
if(!sql_query.exec())
{
qDebug()<<sql_query.lastError();
}
else
{
while(sql_query.next())
{
int id = sql_query.value(0).toInt();
QString name = sql_query.value(1).toString();
int age = sql_query.value(2).toInt();
qDebug()<<QString("id:%1 name:%2 age:%3").arg(id).arg(name).arg(age);
}
}
qDebug()<<name<<QThread::currentThread();
ConnectionPool::closeConnection(db);
end=clock();
cout<< "Running time is: "<<static_cast<double>(end-begin)/CLOCKS_PER_SEC*1000<<"ms"<<endl;
}
Complete test code :
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include"connectionpool.h"
#include
using namespace std;
void getsqlData(QString name)
{
time_t begin,end;
begin=clock();
QSqlDatabase db= ConnectionPool::openConnection();
QSqlQuery sql_query(db);
sql_query.exec(“select * from student”);
if(!sql_query.exec())
{
qDebug()<<sql_query.lastError();
}
else
{
while(sql_query.next())
{
int id = sql_query.value(0).toInt();
QString name = sql_query.value(1).toString();
int age = sql_query.value(2).toInt();
qDebug()<<QString(“id:%1 name:%2 age:%3”).arg(id).arg(name).arg(age);
}
}
qDebug()<<name<<QThread::currentThread();
ConnectionPool::closeConnection(db);
end=clock();
cout<< "Running time is: "<<static_cast(end-begin)/CLOCKS_PER_SEC*1000<<“ms”<<endl;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QStringList list;
list.append(“ui”);
list.append(“fhjd”);
list.append(“vkdll”);
QFuture f=QtConcurrent::map(list,getsqlData);
return a.exec();
}
test result :
Don't explain the result , The writing is very rough .
边栏推荐
- view的子视图的递归
- The goods are full. You must take this knowledge
- D1 哪吒开发板 了解基本的启动加载流程
- 2064: [example 2.1] exchange value
- 2068: [example 2.6] chicken and rabbit in the same cage
- Realization of Joseph Ring with one-way ring linked list
- Experience and learning path of introductory deep learning and machine learning
- Informatics Olympiad all in one 1000: introductory test questions
- The problem of Joseph in Informatics
- Successful job hopping Ali, advanced learning
猜你喜欢
随机推荐
在 Debian 10 上独立安装MySQL数据库
Successfully rated Tencent t3-2, 10000 word parsing
torch_geometric message passing network
Dameng database DM8 Windows environment installation
There was an error installing mysql. Follow the link below to CMD
Record some settings for visual studio 2019
import torch_ Geometric loads some common datasets
Codeforces 1634 F. Fibonacci additions - Fibonacci sequence addition, ideas
Scyther工具形式化分析Woo-Lam协议
RK3399平台开发系列讲解(内核调试篇)2.50、systrace的使用
imagemagick:a gentle introduction to magick++
Cocoapods的相关知识点
Teach you how to create SSM project structure in idea
C language implementation of string and memory library functions
Application of list and Dict
2068: [example 2.6] chicken and rabbit in the same cage
简历 NFT 平台 TrustRecruit 加入章鱼网络成为候选应用链
Wechat web developer tools tutorial, web development issues
上海解封背后,这群开发者“云聚会”造了个AI抗疫机器人
Does jupyternotebook have a Chinese character database. Can you recognize handwritten Chinese in deep learning








![2061: [example 1.2] trapezoidal area](/img/83/79b73ca10615c852768aba8d2a5049.jpg)