Использование WinAPI волокон с Java
Я делаю Java-привязки для игры, которая использует волокна для своей игровой логики. Пример кода того, как в идеале должны работать скрипты:
public static void main(String[] args) {
System.out.println("player: " + PlayerId());
NativeCaller.registerAdditionalThread(() -> {
while(true) {
try {
int player = PlayerId();
int ped = PlayerPedId();
Vec3 pos = GetEntityCoords(ped, true);
System.out.println("ped: " + ped);
}
catch (Error e) {
e.printStackTrace();
}
NativeCaller.wait(1000);
}
});
}
Вы можете видеть, что есть wait
Функция ( см. реализацию) в цикле, который делает что-то. Это не блокировка, это означает, что он приостановит выполнение и возобновит его через некоторое время на другом волокне (и, возможно, потоке).
Проблема в том, что когда блок try-catch выполняется в первый раз, он выдает IllegalMonitorStateException
, Второй раз он работает просто отлично. Я заметил, что это происходит только тогда, когда есть класс, который нужно решить. Вы можете видеть, что я использую Vec3
учебный класс. Если я использую два или более классов, он выдаст одно и то же исключение два или более раз, прежде чем наконец выполнится.
Реализация registerAdditionalThread
:
JNIEXPORT jlong JNICALL impl_registerAdditionalThread(JNIEnv* env_, jobject obj, jobject runnable) {
struct task_t {
jobject runnableTask;
void(*func)();
};
static stack<task_t> runnables;
void(*func)() = []() {
task_t task = runnables.top();
runnables.pop();
JNIEnv* localEnv;
jint res = javaVM->GetEnv((void**)&localEnv, JNI_VERSION_1_8);
jclass runnableCls = localEnv->GetObjectClass(task.runnableTask);
jmethodID mthdRun = localEnv->GetMethodID(runnableCls, "run", "()V");
localEnv->CallVoidMethod(task.runnableTask, mthdRun);
localEnv->DeleteGlobalRef(task.runnableTask);
DEBUGPRINT("Additional script thread terminated");
};
runnables.push({
env_->NewGlobalRef(runnable),
func
});
scriptRegisterAdditionalThread(GetCurrentModuleHandle(), func);
return (jlong)func;
}
Я предполагаю, что это потому, что вся эта информация монитора хранится где-то внутри в локальном хранилище потока, и теряется при изменении потока.
Можно ли вообще сделать wait
работать как задумано?