上文通过JNI调用线程执行已经实现了通过JNI调用Java线程执行。
本文就是说明如何设置线程执行的cpu?
参考Linux中线程与CPU核的绑定就可以设置
本文的代码已经开源在我的GitHub上threadBandCpu
如何将线程绑定到cpu的呢?这里有几个函数(来自参考文章)
int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset); int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t *cpuset); //初始化,设为空 void CPU_ZERO (cpu_set_t *set); //将某个cpu加入cpu集中 void CPU_SET (int cpu, cpu_set_t *set); //将某个cpu从cpu集中移出 void CPU_CLR (int cpu, cpu_set_t *set); //判断某个cpu是否已在cpu集中设置了 int CPU_ISSET (int cpu, const cpu_set_t *set);
这里贴一下几条重要的命令,可能与上文有所重复
g++ -std=c++0x -I/home/jjf/hadoop/jdk1.6.0_45/include/linux/ -I/home/jjf/hadoop/jdk1.6.0_45/include/ -O0 -g3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"ThreadBandCpu.d" -MT"ThreadBandCpu.d" -o "ThreadBandCpu.o" "ThreadBandCpu.cpp" g++ -shared -o "libbandCpu.so" ./ThreadBandCpu.o
其中/home/jjf/hadoop/jdk1.6.0_45是JDK安装目录
ThreadBandCpu.java
public class ThreadBandCpu { static { System.loadLibrary("bandCpu"); } public static native void bandCpu(Runnable r, int cpu); }
BandCpuTest.java
public class BandCpuTest { public static void main(String[] args) { ThreadBandCpu.bandCpu(new Runnable() { @Override public void run() { for(;;){} } }, 2); } }
ThreadBandCpu.h
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class ThreadBandCpu */ #ifndef _Included_ThreadBandCpu #define _Included_ThreadBandCpu #ifdef __cplusplus extern "C" { #endif /* * Class: ThreadBandCpu * Method: bandCpu * Signature: (Ljava/lang/Runnable;I)V */ JNIEXPORT void JNICALL Java_ThreadBandCpu_bandCpu (JNIEnv *, jclass, jobject, jint); #ifdef __cplusplus } #endif #endif
ThreadBandCpu.cpp
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <sched.h> #include "ThreadBandCpu.h" /* Header for class ThreadBandCpu */ #ifdef __cplusplus extern "C" { #endif struct ThreadParams { JavaVM *jvm; jobject callback; int cpu; }; void *myfun(void *ptr) { ThreadParams* p = reinterpret_cast(ptr); JavaVM *jvm = p->jvm; jobject callback = p->callback; int num = p->cpu % sysconf(_SC_NPROCESSORS_CONF); free(p); cpu_set_t mask; CPU_ZERO(&mask); CPU_SET(num, &mask); if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) { fprintf(stderr, "set thread affinity failed\n"); } JNIEnv *env = NULL; jint res; res = jvm->AttachCurrentThread((void **)&env, NULL); if(res < 0) { fprintf(stderr, "Attach VM Thread failed\n"); return NULL; } jclass RunnableInterface = env->GetObjectClass(callback); jmethodID Run = env->GetMethodID(RunnableInterface, "run","()V"); env->CallVoidMethod(callback, Run); jvm->DetachCurrentThread(); pthread_exit(NULL); } /* * Class: ThreadBandCpu * Method: bandCpu * Signature: (Ljava/lang/Runnable;I)V */ JNIEXPORT void JNICALL Java_ThreadBandCpu_bandCpu(JNIEnv *env, jclass cls, jobject obj, jint cpu) { pthread_t tid; ThreadParams* ptr = new ThreadParams(); JavaVM *jvm = NULL; env->GetJavaVM(&jvm); ptr->callback = env->NewGlobalRef(obj); ptr->jvm = jvm; ptr->cpu = (int)cpu; if (pthread_create(&tid, NULL, myfun, reinterpret_cast (ptr)) != 0) { fprintf(stderr, "thread create failed\n"); return ; } pthread_join(tid, NULL); } #ifdef __cplusplus } #endif