[Android]JNI进阶--线程池

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

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

这只是初始化线程

thread.join()

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

thread.detach()

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

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

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#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 task;
                                {   // 获取一个待执行的 task
                                    std::unique_lock 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
        auto commit(F &&f, Args &&... args) -> std::future {
            //直接停止任务
            if (stoped.load())    // stop == true ??
                throw std::runtime_error("commit on ThreadPool is stopped.");
            
            using RetType = decltype(f(
                    args...)); // typename std::result_of::type, 函数 f 的返回值类型
            //自动返回值
            auto task = std::make_shared >(
                    std::bind(std::forward(f), std::forward(args)...)
            );    // wtf !
            std::future future = task->get_future();
            {    // 添加任务到队列
                std::lock_guard 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;
        //线程池
        std::vector pool;
        //任务队列
        std::queue tasks;
        //同步锁
        std::mutex m_lock;
        std::condition_variable cv_task;
        std::atomic stoped;
        std::atomic idlThrNum;
    };
}
#endif

使用方式,这类方法需要声明为static调用的方法

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

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

你可能感兴趣的:([Android]JNI进阶--线程池)