总之,我一直在努力完成以下任务:我希望能够有效地管理很多(数十亿/他们不需要很长时间就能完成,但我是创建数组以进行高速处理,如果我不马上将东西传递给线程,数组变得非常大以至于导致段错误),这些线程在必要时将数据传递给JNI,并且需要存储在向量中。创建矢量管理的JNI线程[C++]
我一直面临两个问题:
第一个是,如果我试图产卵比约45线程都同时运行JNI,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;
}
这听起来像你正在寻找一个线程池。创建一个新的线程相对昂贵,而且你正在做一些疯狂的事情。此外,拥有比您拥有更多并发线程的执行资源通常不会有帮助,并且可能有害。无论如何,我没有看到在实际执行任务之前获得如此远的价值。把它们放在一个有界的队列中,这样,当它变得太远时,无论什么线程产生它们。这可以释放资源来运行实际工作。 –
@JohnBollinger拥有这么多线程似乎是最好的选择来处理其他计算的输出在每〜350us进来。我确实需要使用线程,因为我需要分离出来,让其余部分继续。我会看看一个线程池是否会在我的具体情况下工作。 – JeWe37
你的矢量变得如此之大意味着你的任务执行不能跟上他们的一代。删除创建和加入线程的开销(通过使用线程池)可能有助于解决这个问题,但如果这还不够,那么你就会遇到更深层次的问题。 –