Skip to main content

Eventloop

Overview

The Eventloop module is the basis for other modules that execute their code asynchronously within event loops and threads. It provides efficient management of asynchronous operations without the overhead of multithreading. It is especially useful for creating client-server applications with high-performance requirements.

Features

  • Eventloop uses Java's NIO for asynchronous computation and I/O operations (TCP, UDP).
  • Eliminates the traditional I/O bottleneck for further business logic processing.
  • Can run multiple eventloop threads on available cores.
  • Minimal GC load: arrays and byte buffers are reused.
  • Eventloop can schedule/postpone certain tasks for deferred execution or background execution.
  • Eventloop is single-threaded, so it has no concurrency overhead.
note

Eventloop is a low-level tool that you won't use directly in most cases. Nevertheless, it is an extremely important component that will give you an understanding of the ActiveJ asynchronous model.

Eventloop is an infinite loop, where at each iteration all the tasks that the Selector provides and that are stored in special queues are executed. Each of these tasks must be small, and its execution is called a tick.

The only blocking operation of the Eventloop infinite loop is Selector.select(). This operation selects a set of keys whose corresponding channels are ready for I/O operations. Eventloop asynchronously processes the selected keys and executes the queued runnables in a single thread.

Eventloop works with different types of tasks that are stored in separate queues:

TasksAdded viaDescription
Local tasksEventloop#post Eventloop#postLater Eventloop#postNextAdded from current Eventloop thread
Concurrent tasksEventloop#execute Eventloop#submitAdded from other threads
Scheduled tasksEventloop#schedule Eventloop#delayScheduled to be executed later
Background tasksEventloop#scheduleBackground Eventloop#delayBackgroundSame as Scheduled, but if there are only Background tasks left, Eventloop will be stopped

Eventloop will be stopped if its queues with non-background tasks are empty, the Selector has no selected keys, and the number of concurrent operations in other threads is 0. To prevent Eventloop from closing, set the keepAlive flag. When it's set to true, Eventloop will keep running even without tasks.

Examples

  • BasicExample - a simple example of an eventloop that prints the "Hello World" message.
  • EventloopExample - represents the sequence of operations in eventloops.
note

To run the examples, you need to clone ActiveJ from GitHub:

git clone https://github.com/activej/activej

And import it as a Maven project. Check out tag v5.3. Before running the examples, build the project. These examples are located at activej/examples/core/eventloop.

Basic Example

In this example, we create an eventloop, post a task to it (which prints out the "Hello World" message) and then run the eventloop:

public final class BasicExample {  public static void main(String[] args) {    Eventloop eventloop = Eventloop.create();
    eventloop.post(() -> System.out.println("Hello World"));
    eventloop.run();  }}

See full example on GitHub

Eventloop Example

This example shows how tasks are scheduled in eventloops:

public final class EventloopExample {  public static void main(String[] args) {    Eventloop eventloop = Eventloop.create().withCurrentThread();    long startTime = currentTimeMillis();
    // #2    eventloop.delay(3000L, () -> System.out.println("Eventloop.delay(3000) is finished, time: " + (currentTimeMillis() - startTime)));    eventloop.delay(1000L, () -> System.out.println("Eventloop.delay(1000) is finished, time: " + (currentTimeMillis() - startTime)));    eventloop.delay(100L, () -> System.out.println("Eventloop.delay(100) is finished, time: " + (currentTimeMillis() - startTime)));
    // #1    System.out.println("Before running eventloop, time: " + (currentTimeMillis() - startTime));
    eventloop.run();  }}

If you run the example, you get a result that looks something like this:

Before running eventloop, time: 2Eventloop.delay(100) is finished, time: 106Eventloop.delay(1000) is finished, time: 1001Eventloop.delay(3000) is finished, time: 3001

See full example on GitHub