Skip to content

Timers and thread‐safety in LibGDX

Tom edited this page Oct 4, 2023 · 1 revision

Using LibGDX’s built-in Timer in the game loop

Recently, we have been having issues in our game where an excessive number of threads have been spawned. The main culprit being the incorrect use of Java's built-in timers. This has lead to numerous performance issues, memory leaks, and even occasional crashes. This document will serve as a crash course to guide you on how to properly use timers and generally write thread-safe code in LibGDX.

Understanding the LibGDX Timer

LibGDX's timer is an efficient alternative to Java.util's timer. This is because LibGDX's timer does not spawn a new thread. Instead, it operates within the existing game loop, which makes it more efficient in terms of resource usage, while also remaining thread-safe.

Here is an example of a basic game loop using the LibGDX timer:

@Override
public void create() {     
  Timer.schedule(new Task(){
     @Override
     public void run() {
        // code executed on each frame
     }
  }, 0, 1/60.0f); // runs task every 60th of a second
}

In this example, the "task" is executed every 60th of a second, approximating the typical frame rate of many games. A timer like this may be used to implement animations, or some kind of effect that has a fixed-time animation.

Why Use LibGDX Timer Over Java.util Timer

The Java.util Timer works by spawning a new thread each time its called, which can potentially create issues regarding thread safety. Also, each thread incurs its own overhead in terms of system resources, which will impact the performance of our game.

In contrast, the LibGDX's Timer operates within the main game loop thread which prevents these issues. By not creating new threads, it saves system resources and is better optimized for the game's performance.

Thread Safety in LibGDX

As well as the discussion on timers, there is a wider to discussion to be had about thread-safety more generally in our game. Thread safety is a critical concern in any multi-threaded system. LibGDX advises against multiple threads for game logic for a number of reasons, such as synchronization problems and possible deadlock situations.

For our game you almost defintely won't need to spawn threads, but if you really need to perform some long-running operations like network requests or load resources, use Asynchronous Operations provided by LibGDX. They allow tasks to be executed asynchronously without blocking the rendering thread.

For example:

new Thread(new Runnable() {
   public void run() {
     // perform a long-running operation here without blocking the render thread.
   }
}).start();

Conclusion

Please don't use Java.util.timer.

Clone this wiki locally