为了判断是否完成了队列中数据的写入操作,可以引入一个标志位或计数器,结合条件变量(std::condition_variable
)来实现线程间的同步机制,确保写入操作完成后可以通知主线程或其他逻辑。
改进设计:增加写入完成判断
核心逻辑
-
标志位:
- 使用
std::atomic<bool>
标志当前是否有写入操作正在进行。 - 在写入完成时,将标志位设置为
false
。
- 使用
-
条件变量:
- 在写入操作完成后,通过条件变量通知等待线程。
实现代码
1. 修改 QueueProcessor
类
#include "SharedQueue.h"
#include "DatabaseWriter.h"
#include <atomic>
#include <condition_variable>
#include <thread>
#include <vector>
extern SharedQueue<DataModelA> queueA;
class QueueProcessor {
public:
QueueProcessor() : isFlushing(false) {}
void start() {
workerThread = std::thread(&QueueProcessor::processQueue, this);
}
void stop() {
stopFlag.store(true);
if (workerThread.joinable()) workerThread.join();
}
void flushQueueToDatabase() {
{
std::lock_guard<std::mutex> lock(mtx);
if (isFlushing.load()) {
std::cout << "Flush already in progress...\n";
return;
}
isFlushing.store(true);
}
// 启动异步写入线程
std::thread([this]() {
DatabaseWriter dbWriter;
std::vector<DataModelA> dataBatch;
// 从队列中提取所有数据
queueA.popAll(dataBatch);
if (!dataBatch.empty()) {
dbWriter.writeBatchA(dataBatch);
}
// 写入完成,更新标志位并通知主线程
{
std::lock_guard<std::mutex> lock(mtx);
isFlushing.store(false);
cv.notify_all();
}
}).detach();
}
// 等待写入完成
void waitUntilFlushed() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [this]() { return !isFlushing.load(); });
std::cout << "Flush operation completed.\n";
}
private:
std::atomic<bool> stopFlag = false; // 停止标志
std::atomic<bool> isFlushing; // 写入中标志
std::thread workerThread; // 工作线程
std::mutex mtx; // 用于保护标志位
std::condition_variable cv; // 条件变量
void processQueue() {
while (!stopFlag.load()) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
// 可以监控队列或执行其他任务
}
}
};
2. 主程序调用示例
#include <thread>
#include <chrono>
#include <iostream>
void produceDataA();
int main() {
SharedQueue<DataModelA> queueA;
QueueProcessor processor;
// 启动生产者线程
std::thread producerThread(produceDataA);
// 启动队列处理器
processor.start();
// 模拟写入操作
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "Flushing data to database...\n";
processor.flushQueueToDatabase();
// 等待写入完成
processor.waitUntilFlushed();
// 停止处理器
processor.stop();
producerThread.join();
return 0;
}
功能解释
-
写入判断:
isFlushing
标志位表示当前是否在写入。- 主线程通过
waitUntilFlushed
等待写入完成。
-
非阻塞触发:
flushQueueToDatabase
触发写入后立即返回,写入操作由独立线程完成。
-
等待写入完成:
- 使用
cv.wait
阻塞当前线程,直到写入完成后被通知。
- 使用
-
线程安全:
std::mutex
确保多个线程对isFlushing
标志位的访问安全。
输出示例
Flushing data to database...
Writing DataModelA to database: id=1, value="test1"
Writing DataModelA to database: id=2, value="test2"
Flush operation completed.
设计优点
- 可控性强:主线程可以明确知道写入何时完成,方便后续操作。
- 安全性高:基于条件变量实现线程间同步,避免不必要的忙等待。
- 灵活性:支持多个触发点调用写入,同时保证每次写入操作独立完成。
这种实现适用于需要实时监控写入状态的场景,比如确保写入操作完成后再进行后续逻辑。