C ++串行线程执行程序

时间:2015-11-06 09:41:55

标签: android c++ multithreading c++11 java-native-interface

来自Java环境(特别是Android)我在新线程中执行某些代码时没有遇到任何问题而没有阻塞主线程。 因为我现在必须使用C ++,所以我偶然发现了以下问题。

客户端代码通过JNI执行我的本机(C ++)代码:

JNIEXPORT jbyteArray JNICALL
Java_com_native_project_NativeInterface_processData(JNIEnv *env, jobject instance, jbyteArray inputData_) {
    vector<unsigned char> inputData = jbyteArrayToBytes(env, inputData_);
    const vector<unsigned char> &result = getDataProcessor(env, instance).processData(inputData);
    return bytesTojbyteArray(env, result);
}

DataProcessor getDataProcessor(JNIEnv *env, jobject instance) {
    return DataProcessor(env, instance);
}

然后在我的DataProcessor我想做两个小事:

  • 处理数据并尽快返回
  • 将数据写入活动日志(例如数据库)而不延迟响应(因此首先返回响应,然后记录数据)

示例代码:

class BasicAsync {
private:
    void logToDB(const vector<unsigned char> &inputData) {
        // connect to DB and write data to it
    }

    vector<unsigned char> compute(const vector<unsigned char> &inputData) {
        vector<unsigned char> result = vector<unsigned char>();
        // rocket-science computation in here
        return result;
    }

public:
    vector<unsigned char> processData(const vector<unsigned char> &inputData) {
        // perform data computation and produce output
        vector<unsigned char> result = compute(inputData);

        // create a thread that writes the data to activity log without delaying the response return
        logToDB(inputData);

        //return result while data is written to activity log
        return result;
    }
}

我的主要观点是:

  1. 是否可以在C ++中使用(我使用的是C ++ 11)?
  2. 如果将数据写入数据库需要一段时间,那么DataProcessor对象在此期间会发生什么事情(因为它应该在通过JNI返回响应后销毁,因为它的生命周期范围结束 - 也许我遗漏了一些东西这里)?
  3. 是否有任何串行线程执行器,以便我可以向数据库写一些东西(它们将被放入FIFO队列并在同一个线程中按顺序保存)?

2 个答案:

答案 0 :(得分:2)

  1. 考虑Active Object Pattern的变体来实现一个串行执行队列,以执行必须序列化的长期运行的工作:
  2. #include <thread>
    #include <mutex>
    #include <functional>
    #include <queue>
    
    class SerialExecutionQueue
    {
    public:
        typedef std::function<void()>   QueueItem;
    
        SerialExecutionQueue() :
        m_shouldQuit(false),
        m_executor([this]()
           {
               executor();
           })
        {
    
        }
    
        void enqueueWork(QueueItem item)
        {
            {
                std::lock_guard<std::mutex> l(m_mutex);
                m_queue.push(item);
            }
            m_cv.notify_all();
        }
    
        void executor()
        {
            while (!m_shouldQuit)
            {
                std::unique_lock<std::mutex> lock(m_mutex);
                while (m_queue.size())
                {
                    auto item = m_queue.front();
                    m_queue.pop();
                    m_mutex.unlock();
                    item();
                    m_mutex.lock();
                }
                m_cv.wait(lock);
            }
        }
    
    private:
        bool                    m_shouldQuit;
        std::condition_variable m_cv;
        std::mutex              m_mutex;
        std::queue<QueueItem>   m_queue;
        std::thread             m_executor;
    };
    
    int main(int argc, const char * argv[])
    {
    
        SerialExecutionQueue queue;
    
        queue.enqueueWork([]()
              {
                  std::cout << "Did some work 1" <<std::endl;
              });
    
    
        queue.enqueueWork([]()
              {
                  std::cout << "Did some work 2" <<std::endl;
              });
    
        sleep(1);
    
        queue.enqueueWork([]()
              {
                  std::cout << "Did some work 3" <<std::endl;
              });
    
        sleep(10);
        return 0;
    }
    

    输出:

    Did some work 1
    Did some work 2
    Did some work 3
    

答案 1 :(得分:0)

在2011年之前,必须直接使用本地API(如pthreads)或部署第三方包装器库(如boost中的那些),但自2011年起,C ++提供了一个非常肥胖的标准化thread界面。

也许您先亲自看看,尝试一下,并在帖子中添加更具体的问题;然后我会相应地扩展这个答案。