Basic Java Threads


Java provides classes and methods to create multiple threads inside your Java process. This allows you to run multiple different pieces of code at the same time. In the code below each of the worker threads prints out that they have started, wait a random amount of time before printing their message, wait another random amount of time and print that they have stopped. Each time the program runs the output will be in a different order.

public class Worker extends Thread
{
    private String message;

    public Worker()
    {
        this.message = "Hello from Thread-" + this.getId();
    }

    @Override
    public void run()
    {
        System.out.println("Thread-" + getId() + " started");
        try {
            Thread.sleep((long)(Math.random() * 1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(message);
        try {
            Thread.sleep((long)(Math.random() * 3000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Thread-" + getId() + " stopped");
    }
}

To run the following Worker class, I created a simple Driver that creates 5 instances of worker and starts them all.

import java.util.ArrayList;

public class Driver
{
    public static void main(String[] args)
    {
        ArrayList<Worker> workers = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            workers.add(new Worker());
        }

        workers.forEach(Thread::start);
        workers.forEach((Worker worker) -> {
                try {
                    worker.join();
                } catch (InterruptedException e) {
                    System.err.println("Failed joining thread " + worker.getId());
                }
        });
    }
}

Another option is to create a Runnable and instantiate a new thread with it. This approach means that you can define the Runnable method inline, saving on complexity if the function to run is simple. By instantiating a Thread with a runnable it avoids having to create a new class for simple functions e.g. sending a notification to a server (takes time but does not need to block the main process).

Thread workerThread = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Thread started");
    }
});
workerThread.start();

GNU nano 2.9.3 basic-java-threads.md

public class Driver { public static void main(String[] args) { ArrayList workers = new ArrayList<>(); for (int i = 0; i < 5; i++) { workers.add(new Worker()); }

    workers.forEach(Thread::start);
    workers.forEach((Worker worker) -> {
            try {
                worker.join();
            } catch (InterruptedException e) {
                System.err.println("Failed joining thread " + worker.getId());
            }
    });
}

}


---

Another option is to create a Runnable and instantiate a new thread with it. This approach means that yo$
```java
Thread workerThread = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Thread started");
    }
});
workerThread.start();

GNU nano 2.9.3 basic-java-threads.md

public class Driver { public static void main(String[] args) { ArrayList workers = new ArrayList<>(); for (int i = 0; i < 5; i++) { workers.add(new Worker()); }

    workers.forEach(Thread::start);
    workers.forEach((Worker worker) -> {
            try {
                worker.join();
            } catch (InterruptedException e) {
                System.err.println("Failed joining thread " + worker.getId());
            }
    });
}

}


---

Another option is to create a Runnable and instantiate a new thread with it. This approach means that yo$
```java
Thread workerThread = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Thread started");
    }
});
workerThread.start();