Skip to main content

Eventloop

Overview#

Eventloop module is the foundation of other modules that run their code asynchronously inside event loops and threads. It provides efficient management of asynchronous operations without multithreading overhead. Particularly useful for building client-server applications with high-performance requirements.

Features#

  • Eventloop utilizes Java's NIO to allow asynchronous computations and I/O operations (TCP, UDP).
  • Eliminates traditional bottleneck of I/O 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/delay certain tasks for later execution or background execution.
  • Eventloop is single-threaded, so it doesn't have concurrency overhead.
note

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

Eventloop represents an infinite loop, where each loop executes all the tasks that are provided by Selector or stored in special queues. Each of these tasks should be small and its execution is called a tick.

The only blocking operation of 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 selected keys and executes 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, Selector has no selected keys and the amount of concurrent operations in other threads equals 0. To prevent Eventloop from closing, set a keepAlive flag. When it's set to true, Eventloop will continue running even without tasks.

Examples#

  • BasicExample - a simple example of an eventloop which prints out a "Hello World" message.
  • EventloopExample - represents the sequence of operations execution 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 v4.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 is printing out "Hello World" message) and then start 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 represents 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'll receive an output which looks something like this:

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

See full example on GitHub