当前位置:网站首页>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 .
边栏推荐
- 1414: [17noip popularization group] score
- [brush title] probability of winning a draw
- 微信web开发者工具使用教程,web开发问题
- NVIDIA Jetson Nano Developer Kit 入门
- leetcode 47. Permutations II full permutations II (medium)
- torch_ About the geometric Mini batch
- Stm32f1 and stm32cubeide programming examples - device driver -eeprom-at24c256 driver
- The problem of Joseph in Informatics
- Encryptor and client authenticate with each other
- 安装MySQL时出错,照着下面这个链接,做到cmd就不行了
猜你喜欢

Successfully rated Tencent t3-2, 10000 word parsing

imagemagick:a gentle introduction to magick++

创新实训(十一)开发过程中的一些bug汇总

单向环形链表实现约瑟夫环

618进入后半段,苹果占据高端市场,国产手机终于杀价竞争

torch_geometric mini batch 的那些事

Implementing tensorflow deep learning framework similarflow with numpy

Application of binary search -- finding the square root sqrt of a number

Qualcomm platform development series (Protocol) QMI brief introduction and usage

Introduction to application design scheme of intelligent garbage can voice chip, wt588f02b-8s
随机推荐
1005: estimation of the earth's population carrying capacity
Paw 高级使用指南
Codeforces 1629 A. download more RAM - simple greed
Semantic segmentation with pytorch
Script引入CDN链接提示net::ERR_FILE_NOT_FOUND问题
Code debugging - print log output to file
torch_ About the geometric Mini batch
2061: [example 1.2] trapezoidal area
Django note 21: querying databases using native SQL
高通平台开发系列讲解(协议篇)QMI简单介绍及使用方法
【云原生 | Kubernetes篇】Kubernetes 网络策略(NetworkPolicy)
2064: [example 2.1] exchange value
Multi source BFS problem template (with questions)
torch_ geometric message passing network
Redis message queue repeated consumption
Stm32f1 and stm32cubeide programming examples - device driver -eeprom-at24c256 driver
Informatics Olympiad all in one 1000: introductory test questions
数据类型转换和条件控制语句
The goods are full. You must take this knowledge
A brief introduction to Verilog mode