2015-11-06 65 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接口。也許你先看看這個,試試看,並在你的文章中添加更具體的問題;然後我會相應地擴展這個答案。