2015-11-06 34 views
1

来自Java环境(特别是Android)我从来没有任何问题在新线程中执行一些代码而不阻塞主线程。因为我现在必须使用C++,所以我偶然发现了这个问题。C++串口线程执行器

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

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我希望做两个thigs:

  • 过程中的数据,并尽快返回它
  • 将数据写入活动日志(例如数据库)而不延迟响应(所以首先返回响应然后记录数据)

示例代码:

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; 
    } 
} 

我主要concers是:

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

我不知道jni,b您可以创建一个写入数据库的线程并立即将其分离。 – MikeMB

+0

但是,请注意创建一个线程是一个代价高昂的操作,因此如您所建议的那样,使用单个专用线程进行日志记录的话肯定会更高效。 – MikeMB

回答

2
  1. 考虑Active Object Pattern的变体来实现串行执行队列做你必须序列化长期运行的工作:
#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 
0

2011年之前,人们不得不直接使用像pthreads的原生API或部署第三方包装库,像那些从提升,但2011年以来,C++提供了一个比较胖的标准化thread接口。也许你先看看这个,试试看,并在你的文章中添加更具体的问题;然后我会相应地扩展这个答案。