Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Threads

A thread is a separate sequence of instructions inside a program. Normally a program runs code line by line in one thread — the main one, called main. If you start several threads, they run at the same time: while one waits for a network reply, another processes data. Don't confuse them with streams (the Stream API) — they are different things.

The first thread

A thread is created with the Thread class by giving it a task — a lambda with no parameters. The start() method starts the thread, and join() makes the current thread wait until it finishes:

void main() throws InterruptedException {
    Thread worker = new Thread(() -> IO.println("Hello from another thread"));
 
    IO.println("Starting");
    worker.start();
    worker.join();
    IO.println("Done");
}

Output:

Starting
Hello from another thread
Done

Thanks to join() the "Done" line is guaranteed to be printed last. join and other waiting methods may throw the checked InterruptedException — if the thread is asked to stop waiting — so main declares throws.

Order is not guaranteed

Threads run independently, and the operating system decides which one gets the processor. That's why the output order of two threads changes from run to run:

void count(String name) {
    for (int i = 1; i <= 3; i++) {
        IO.println(name + i);
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            return;
        }
    }
}
 
void main() throws InterruptedException {
    Thread a = new Thread(() -> count("A"));
    Thread b = new Thread(() -> count("B"));
 
    a.start();
    b.start();
    a.join();
    b.join();
}

Output (one possible run — your order may differ):

B1
A1
B2
A2
A3
B3

Within one thread the order is preserved: A1 always comes before A2. But how the A and B lines get mixed can't be predicted.

Pauses

Thread.sleep pauses the current thread for a given time. It's handy for imitating slow work — a server request or reading a big file:

void main() throws InterruptedException {
    IO.println("Loading...");
    Thread.sleep(Duration.ofMillis(500));
    IO.println("Loaded");
}

Output:

Loading...
Loaded

Thread names

Every thread has a name. Thread.currentThread().getName() returns it, so you can find out which thread the code is running in. A convenient way to set a name is the Thread.ofPlatform() builder:

void main() throws InterruptedException {
    Thread worker = Thread.ofPlatform()
            .name("loader")
            .start(() -> IO.println("Running in: " + Thread.currentThread().getName()));
 
    worker.join();
    IO.println("Running in: " + Thread.currentThread().getName());
}

Output:

Running in: loader
Running in: main

The builder's start method both creates and starts the thread.

A result from a thread

The lambda in a Thread returns nothing. A simple way to collect results is to give each thread its own array cell and read the array after join:

void main() throws InterruptedException {
    int[] sums = new int[2];
 
    Thread first = new Thread(() -> sums[0] = IntStream.rangeClosed(1, 500).sum());
    Thread second = new Thread(() -> sums[1] = IntStream.rangeClosed(501, 1000).sum());
    first.start();
    second.start();
    first.join();
    second.join();
 
    IO.println("Sum from 1 to 1000: " + (sums[0] + sums[1]));
}

Output:

Sum from 1 to 1000: 500500

The threads write to different cells and don't get in each other's way, and join guarantees both have finished by the time we read. Thread pools make getting results easier — they're the topic of the next lesson.

Common mistake

If you call run() instead of start(), no new thread is created: the task simply runs in the current thread, like an ordinary method:

void main() {
    Thread worker = new Thread(() -> IO.println("Running in " + Thread.currentThread().getName()));
 
    worker.run();
}

Output:

Running in main

There's no error, but there's no parallelism either. To run code in a separate thread, always call start().

Thanks for reading!

Donate to the site — we work hard for you.