美文网首页犄角旮旯C/C++
指定线程运行任务

指定线程运行任务

作者: cx7 | 来源:发表于2018-08-17 18:57 被阅读0次

使用场景

使用某些第三方库时,会遇到线程安全的问题.
如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();
}

各个平台上的实现原理基本是一致的 因为语言或者平台特点有些许差别

相关文章

  • 指定线程运行任务

    使用场景 实现原理 Object-C实现 C++ 实现 各个平台上的实现原理基本是一致的 因为语言或者平台特点有些许差别

  • Spring中任务调度

    任务调度 任务调度即在特定的时间点执行指定的操作。任务调度本身设计多线程并发,运行时间规则制定及解析,运行现场保持...

  • iOS开发-dispatch_sync阻塞主线程造成死锁

    运行结果:主线程卡死 原因:同步任务会阻塞当前线程,然后把 Block 中的任务放到指定的队列中执行,只有等到 B...

  • RxJava自带线程池监控和管理的探索之旅

    背景 RxJava很方便的切换主子线程、指定任务运行的线程,在这个便利之后还隐藏着很多问题。比如IO schedu...

  • 03给女朋友讲讲并发编程-进程与线程的监控

    一、线程运行-查看和杀死(Windows) 1.查看进程列表 查看指定名称进程列表 2.杀死指定进程 二、线程运行...

  • Handler的工作原理(一)Handler的使用

    Handler的运行机制也是Android主要的消息机制;Handler的主要作用是将一个任务切换到某个指定的线程...

  • 线程池

    线程池ThreadPoolExecutor 运行步骤:1,任务进来 新建核心线程执行任务 直到核心线程池占满 ...

  • 线程间通信实例

    如何让两个线程依次执行? 主线程等待子线程运行 那如何让 两个线程按照指定方式有序交叉运行呢? 多线程交替打印AB...

  • android 消息机制

    1.android 消息机制主要是指Handler的运行机制,Handler可以轻松地把一个任务切换到指定地的线程...

  • RxJava的使用之Scheduler

    Scheduler为调度器,也可以叫做线程控制器。RxJava通过它来指定每一段代码在那个线程中运行。在不指定线程...

网友评论

    本文标题:指定线程运行任务

    本文链接:https://www.haomeiwen.com/subject/jrvtiftx.html