Killing zombies in a multi-threaded java application

Accname

2D-Graphics enthusiast
Reaction score
1,462
Hi, still working with java and lwjgl here.
I am setting up a multi-threaded java application with one thread covering graphics updates and inputs from mouse and keyboards and another doing periodical updates on the games entity objects.
However, when i close the application, whether it is by stopping the jvm in eclipse or by clicking the X-Button of the window (calling System.exit(0)) the threads do not get properly killed.
When opening the task manager i can still see them active, and they stack up the more often i start the application.
I have to manually kill the processes.

So what should i do? I thought the system.exit command would kill all threads in the thread-group "main" but apparently it doesnt. Any ideas?
 

s3rius

Linux is only free if your time is worthless.
Reaction score
130
You should probably properly close all threads:

Code:
public void onProgramExit(){
    for( each thread t ){
        try{
            t.join();
        } catch(InterruptedException ex){
        }
    }
}

.join will make the program wait for the thread to finish. Of course you need some way to tell the thread that it has to be shut down. I don't know what facilities Java provides for that, but usually you'd just take a (global) boolean value like g_shutDown. Then you set it to true once you want to exit the program.
All threads have to periodically check whether g_shutDown is true. If it is the thrad will kill itself. Via t.join() you just order your main thread to wait for each thread's self termination.

PS:
On related note: You should not use System.exit() to shut down your program.

From the Oracle Portability Cookbook:
"The System.exit method forces termination of all threads in the Java virtual machine. This is drastic....System.exit should be reserved for a catastrophic error exit, or for cases when a program is intended for use as a utility in a command script that may depend on the program's exit code."

Usually a program should be closed by just returning from the static main function.

PPS:
Actually.. the task manager doesn't show threads but processes, so if your program shows up multiple times in the task manager that means it's not the multithreading but the improper termination of the entire process (=your program) that isn't doing well.
Unless by multithreading you meant creating a bunch of new processes.
 

Accname

2D-Graphics enthusiast
Reaction score
1,462
Thanks for the answer.
But i still have some problems.

How am i going to stop the threads?
Using a public static variable in the main-thread which is used in the while-loops in the other threads is not really going to work since some systems could cache the frequently used variables (like this boolean) in the cpu cache and not register a change on it which is done by another thread.
I could make the variable volatile which will force reading/writing from main memory always but will slow down access to it as well.

I could theoretically use the Thread.stop() method but its said to be deprecated because it will unlock all semaphores or "locks" as java calls it.
However, i think if i use it to shut down all threads at once it might be okay, or not?

I didnt know about System.exit() stopping all java threads, i was expecting it to work like the C equivalent, lol. Thanks mate.

And yes i am using Threads and not processes, but each time you start a java application it will also create a new process and although i closed the window and freed the display the process was still running, this is why i thought it would be zombies, i guess although the window is closed some threads are still running.
 

s3rius

Linux is only free if your time is worthless.
Reaction score
130
Yes, the window and the thread are two seperate items. Shutting down one doesn't necessarily mean shutting down the other.

And using multithreading means that everytime your threads have to talk to each other you have to endure performance loss.

So the two best ways I can think of are:

1) Use an AtomicBoolean (a simple volatile Boolean isn't enough), make it a public static somewhere and use it as a flag to tell threads to shut down.
2) Put a function into the class you instanciate your threads from (the one that implements Runnable) and use this function to set a thread-local shutdown variable. Then you can call this function for every thread once you want them to finish.

One way or another you need synchronized read-write access to a variable. The second option would probably be cheaper on the long run.
 

Accname

2D-Graphics enthusiast
Reaction score
1,462
I am using a public static boolean in the Main-Class (the class with the static main method) which is used in the while-loops of the other threads created by this class.
However, i did forget to set it to volatile.

I guess i will need multi-threading, right now i am using it only to learn how to actually use it, but i guess it will be needed once online-multiplayer is implemented, and probably 2 threads for the actual game for performance gain.
One thread updating the graphics and taking input from mouse and keyboard and another for periodically updating all entity classes and AI-players.
I am curious, is the sleep(int) method of thread a reliable way to set a frame rate for threads?
 

s3rius

Linux is only free if your time is worthless.
Reaction score
130
sleep(x) isn't a reliable way.

1) It doesn't necessarily sleep x milliseconds. It may sleep a bit longer or shorter. It's very inaccurate.
2) Executing your code takes time too, so you would have to calculate that into the sleep(x), which doesn't exactly make things more accurate.

I'd be very careful of just adding more threads to your program unless you like heisen bugs.
There's no need to add threads to handle input/output, sound, or stuff like that.

Usually you don't use more than 2 threads (1 main thread, 1 for network).

Where you really want to have more threads is for computing power alone. And for that you can use so-called worker threads.

Code:
class ModelCalculation implements Runnable{
    override public void run(){
        //Do your CPU-intensive model calculations or anything else here
    }
}

class main{
    public static void main(String[] args){
    
        Thread t = new ModelCalculation();
    
        while(gameIsRunning){
            t.run();
            
            DoGameLogic();
            DoInput();
        
            t.join();
            
            RenderModels();
        }
    }
}

How it works:
Everytime your main loop runs it:
1) Starts the thread t
2) It does some work on it's own (meanwhile t is working on models)
3) It now waits for t to finish doing it's work
4) It then uses t's work to render the models.

This way you keep threads out of your program architecture as much as possible (which is a very good thing!) while you can use additional threads for their most important job: pure CPU power.

By the way: don't put opengl calls into more than one thread. I don't know lwjgl but generally OpenGL isn't thread-safe. So calling stuff from two different threads might mess up things seriously.
Also, OpenGL is only the driver. The connection between your GPU and your CPU. Most work is done on the GPU, which is basically like a different thread. So putting OpenGL calls into a different thread will not get you the performance improvement you're looking for.
 

Accname

2D-Graphics enthusiast
Reaction score
1,462
I know, i have put all openGL calls into the main (graphics) thread.
The other thread is just periodically updating the games objects. Like scanning for targets in range or moving them on the map.
The second thread is just doing calculating and updating values in the games entity objects.

But of course it would be nice that it is always running the same speed.

Edit:
Could i make the second (unit-update) thread wait on the main (graphics) thread and the main (graphics) thread is sending a notify in every frame to balance the frame rate between both threads? So they will begin their update cycles together but calculate different things simultaniously.
 

s3rius

Linux is only free if your time is worthless.
Reaction score
130
One could probably get this to work, but to reiterate: The worker-thread concept is best in my opinion.
I see hardly any drawbacks, it encapsulates threading and it will potentially save you hours and hour of painful error search.

But if you want to burn your hands to see how it feels, go ahead :)
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top