美文网首页Android-NDK/JNI
[Android]JNI进阶--线程池

[Android]JNI进阶--线程池

作者: CangWang | 来源:发表于2019-02-27 21:06 被阅读23次

    当一些异步的任务的时候,使用C++来创建线程来做任务的时候,
    可以引用std::thread这个库
    使用方法如下,创建一个线程,里面通过std::bind来绑定方法任务。

    std::thread thread = std::thread(std::bind(&类名::方法名,this 参数);
    

    这只是初始化线程

    thread.join()
    

    等着线程执行完成之后,主线程才能执行下去,此时主线程会立刻释放子线程占用的资源

    thread.detach()
    

    主线程不需要等待子线程执行完成,主线程和子线程分离

    这是简单的线程调用,而C++中并没封装好线程池给我们使用。这里网上找了一个例子,可以简单看看注释。

    #include <functional>
    #include <vector>
    #include <thread>
    #include <mutex>
    #include <atomic>
    #include <queue>
    #include <condition_variable>
    #include <future>
    
    #ifndef THREAD_POOL_H
    #define THREAD_POOL_H
    
    namespace std {  //声明std的作用域
    #define MAX_THREAD_NUM = 256
    
        class MagicThreadPool {
        public:
            //内联函数,
            inline MagicThreadPool(unsigned short size = 4) : stoped{false} {
                //线程池大小
                idlThrNum = size < 1 ? 1 : size;
                for (size = 0; size < idlThrNum; ++size) {   //初始化线程数量
                    // 只有一次构造函数,不调用拷贝构造函数,速度最快
                    pool.emplace_back(
                            [this] { // 工作线程函数
                                while (!this->stoped) {
                                    //声明任务
                                    std::function<void()> task;
                                    {   // 获取一个待执行的 task
                                        std::unique_lock<std::mutex> lock{this->m_lock};// unique_lock 相比 lock_guard 的好处是:可以随时 unlock() 和 lock()
                                        this->cv_task.wait(lock,
                                                           [this] {
                                                               return this->stoped.load() ||
                                                                      !this->tasks.empty();
                                                           }
                                        ); // wait 直到有 task
                                        if (this->stoped && this->tasks.empty())
                                            return false;
                                        task = std::move(this->tasks.front()); // 取一个 task
                                        this->tasks.pop();
                                    }
                                    idlThrNum--;
                                    //运行任务
                                    task();
                                    idlThrNum++;
                                }
                            }
                    );
                }
            }
            //析构函数
            inline ~MagicThreadPool() {
                //停止全部任务
                stoped.store(true);
                cv_task.notify_all(); // 唤醒所有线程执行
                for (std::thread &thread : pool) {
                    //thread.detach(); // 让线程“自生自灭”
                    if (thread.joinable())
                        thread.join(); // 等待任务结束, 前提:线程一定会执行完
                }
            }
    
            //模板,需要声明类的类型,自动匹配返回值
            template<class F, class... Args>
            auto commit(F &&f, Args &&... args) -> std::future<decltype(f(args...))> {
                //直接停止任务
                if (stoped.load())    // stop == true ??
                    throw std::runtime_error("commit on ThreadPool is stopped.");
                
                using RetType = decltype(f(
                        args...)); // typename std::result_of<F(Args...)>::type, 函数 f 的返回值类型
                //自动返回值
                auto task = std::make_shared<std::packaged_task<RetType()> >(
                        std::bind(std::forward<F>(f), std::forward<Args>(args)...)
                );    // wtf !
                std::future<RetType> future = task->get_future();
                {    // 添加任务到队列
                    std::lock_guard<std::mutex> lock{
                            m_lock};//对当前块的语句加锁  lock_guard 是 mutex 的 stack 封装类,构造的时候 lock(),析构的时候 unlock()
                    tasks.emplace( //放入任务到任务池
                            [task]() { // push(Task{...})
                                (*task)();
                            }
                    );
                }
                cv_task.notify_one(); // 唤醒一个线程执行
    
                return future;
            };
    
            //空闲线程数量
            int idlCount() { return idlThrNum; }
    
        private:
            using Task = std::function<void()>;
            //线程池
            std::vector<std::thread> pool;
            //任务队列
            std::queue<Task> tasks;
            //同步锁
            std::mutex m_lock;
            std::condition_variable cv_task;
            std::atomic<bool> stoped;
            std::atomic<int> idlThrNum;
        };
    }
    #endif
    

    使用方式

    pool->commit(类名::方法名,参数);
    

    这里注意一定不要这里是一个MagicThreadPool.h文件,千万别想因为代码好看分成两个h和cpp来写。
    因为cpp将会编译好的代码,是无法更改的,无法进行模板在线程调用方法中的参数推导。会无法编译通过。
    如果想看具体的流程可以看我MagicCamera3的代码
    地址是MagicCamera3 https://github.com/cangwang/MagicCamera3,欢迎大家下载和点赞,如果有问题,也可以进我的组件化群1和群2,来讨论问题。

    相关文章

      网友评论

        本文标题:[Android]JNI进阶--线程池

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