使用场景
使用某些第三方库时,会遇到线程安全的问题.
如OpenGL是非线程安全的 对OpenGL API的调用需要在同一个线程中完成.
实现原理
假定runOnAssignThread这个API 可以把任务投递到指定线程运行
假设有多个线程 一个指定的任务运行线程 其余都是业务线程
在业务线程的运行过程中 将会调用到runOnAssignThread
就将任务投递到了任务线程运行 业务线程不真正运行这个任务
伪代码实现:
任务运行函数:
void runOnAssignThread(task task) {
if (当前就处于任务线程) {
task();//直接执行任务
} else {
//把任务插入到一个队列中
}
}
相应的 在任务线程中 需要不断的处理队列中的任务
任务线程中:
for (;;) {
if (队列有任务) {
task = list.front();//取出任务
task();//运行任务
}
}
大致的运行原理如此 实际上还有多线程对任务队列的访问同步、任务线程的启动和退出条件这些细节需要考虑
Object-C实现
iOS的GCD编程封装了底层的线程操作
dispatch_sync可以直接指定在某个diapatch_queue_t中同步运行任务
这使得iOS的runOnAssignThread的实现容易了很多
dispatch_queue_t assignQueue; //此处假设这个队列已经申请好了
void runOnAssignQueue (void (^task)(void)) {
if (dispatch_get_current_queu() == assignQueue) {
task();
} else {
dispatch_sync(assignQueue, task);
}
}
C++ 实现
#include "runOnVideoQueue.hpp"
#include <iostream>
#include <thread>
#include <list>
#include <mutex>
#include <condition_variable>
typedef std::function<void()> task;
std::list<task> taskList;
std::mutex taskMutex;
std::condition_variable taskCond;
std::__thread_id videoQueueThreadID;
bool endFlag = false;
void runOnVideoQueue(task task) {
if (std::this_thread::get_id() == videoQueueThreadID) {
task();
} else {
std::unique_lock<std::mutex> lock(taskMutex);
taskList.push_back(task);
endFlag = true;
taskCond.notify_one();
}
}
void handleEventOnVideoQueue() {
for (;;) {
task task = nullptr;
{
std::unique_lock<std::mutex> lock(taskMutex);
taskCond.wait(lock, [] {
return endFlag;
});
if (taskList.empty()) {
std::cout << "error:empty task list";
continue;
}
task = taskList.front();
taskList.pop_front();
endFlag = false;
}
task();
}
}
void runOnVideoQueueTest() {
videoQueueThreadID = std::this_thread::get_id();
std::cout << "video queue thread id:" << videoQueueThreadID << std::endl;
std::thread otherQueue([] {
runOnVideoQueue([](){
std::cout << "add on other Queue but run on video queu biu biu biu" << std::endl;
});
});
otherQueue.join();
runOnVideoQueue([](){
std::cout << "run on video queu biu biu biu" << std::endl;
});
handleEventOnVideoQueue();
}
各个平台上的实现原理基本是一致的 因为语言或者平台特点有些许差别
网友评论