簡體   English   中英

創建矢量管理的JNI線程[C ++]

[英]Creating vector managed JNI threads [C++]

簡而言之,我一直在努力實現以下目標:我希望能夠有效地管理很多工作(數十億美元/它們花了很長時間才能完成,但是我正在創建要快速處理的陣列,如果我沒有立即將東西傳遞給線程,數組變得如此之大,會導致段錯誤(segfaults),這些線程會在必要時將數據傳遞給JNI,並需要存儲在向量中。

我一直面臨兩個問題:

第一個是,如果我嘗試產生同時運行JNI的45個以上線程,則Java崩潰。 如果他們不能同時運行所有程序,則可以正常運行,但是我從GC那里收到了很多抱怨,即它們沒有足夠的內存,盡管似乎沒有任何影響。

第二個問題是,如果我以目前的速度生成線程,那么我用來管理並隨后加入它們的向量將太大。

因此,總而言之,我需要一種快速的方法來跟蹤正在創建的線程,而又不會花費太多時間。

//g++ -std=c++11 -I/usr/lib/jvm/java-8-openjdk/include -I/usr/lib/jvm/java-8-openjdk/include/linux cpptest/Test.cpp -L/usr/lib/jvm/java-8-openjdk/jre/lib/amd64/server -ljvm -lpthread
#include <jni.h>
#include <iostream>
#include <thread>
#include <string.h>
#include <vector>
#include <chrono>
#include <mutex>
#include <fstream>
#include <algorithm>

jclass cls;
jmethodID mid;
JNIEnv* env;
JavaVM* jvm;
std::mutex m;

typedef struct {
    long seed;
    int chunkX;
    int chunkZ;
    int eyes;
} Stronghold;

void ThreadFunc(Stronghold strhld, std::ofstream *outfile) {
  jvm->AttachCurrentThread((void**)&env, NULL);
  jlongArray rt = (jlongArray)env->CallStaticLongMethod(cls, mid, (jlong)strhld.seed, (jint)strhld.chunkX, (jint)strhld.chunkZ, (jint)strhld.eyes);
  jsize size = env->GetArrayLength(rt);
  std::vector<long> rtVec(size);
  env->GetLongArrayRegion(rt, 0, size, &rtVec[0]);
    jvm->DetachCurrentThread();
    std::string write;
    m.lock();
  for(long &element : rtVec) {
        write = std::to_string(element) + "; ";
    *outfile << write;
  }
    *outfile << std::endl;
    m.unlock();
}

int main(int argc, char* argv[]) {
  std::ofstream outfile("./new.txt",std::ofstream::binary);
    std::vector<std::thread> threads;

  const int kNumOptions = 3;
  JavaVMOption options[kNumOptions] = {
    { const_cast<char*>("-Xmx512m"), NULL },
    { const_cast<char*>("-verbose:gc"), NULL },
    { const_cast<char*>("-Djava.class.path=/home/jewe37/Desktop/"), NULL }
  };

  JavaVMInitArgs vm_args;
  vm_args.version = JNI_VERSION_1_8;
  vm_args.options = options;
  vm_args.nOptions = sizeof(options) / sizeof(JavaVMOption);

  env = NULL;
  jvm = NULL;
  JNI_CreateJavaVM(&jvm, reinterpret_cast<void**>(&env), &vm_args);

  const char* kClassName = "Processor";
  cls = env->FindClass(kClassName);
  if (cls == NULL) {
    std::cerr << "FINDCLASS" << std::endl;
        return 1;
    }

  const char* kMethodName = "ProcessSeed";
  mid = env->GetStaticMethodID(cls, kMethodName, "(JIII)[J");
  if (mid == NULL) {
    std::cerr << "FINDMETHOD" << std::endl;
        return 1;
    }

  Stronghold strhld;

    for(int i = 0; i < std::stoi(argv[1]); i++) {
        strhld = {i, i*2, i*3, i*4};
        threads.emplace_back(ThreadFunc, strhld, &outfile);
        std::this_thread::sleep_for(std::chrono::microseconds(50));
    }

    std::cout << threads.size() << std::endl;

    for (std::thread &thread : threads) if (thread.joinable()) thread.join();

  jvm->DestroyJavaVM();

  outfile.close();
  return 0;
}

您不能在線程之間共享JNIEnv。 它必須是每個線程的。 使env在ThreadFunc()本地。 這個問題在這里得到了徹底解答。 另外,不要忘記在退出本機線程之前將其分離。

您可以始終使用互斥鎖,並且這種方式確保僅通過單線程訪問JVM:

http://jnicookbook.owsiak.org/recipe-no-027/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM