What is a thread?
A Thread in Java is a unit of execution within a process. Every Java program has atleast one thread (the main() thread). If we do not create a thread explicitly, our program runs on the main thread.
A process can therefore contain multiple threads. For this reason, creating threads is a more lightweight action compared to the resources it takes for the creation of a process. Threads terminate quickly as well compared to processes.
Why to use Multithreading?
- To execute two or more threads at the same time and take advantage of multicore architectures
- To run async background tasks such as logging, IO tasks etc
- Run isolated code in parallel to increase computation speed for CPU bound processes
- To create watchers for configuration changes
How to create threads?
Let’s look at some common ways of creating Threads in Java. There are a couple of simple ways to create threads in Java, namely
- Implement the java.lang.Runnable interface and override the run() method
- Extend the java.lang.Thread class and override the run() method
Method 1: Extend the java.lang.Thread class and override the run() method
public class Main {
System.out.println("Running in main thread.");
Thread myThread = new MyThread();
myThread.setName("--- MyThread ---");
myThread.start(); // This runs the thread
}
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("Hello from " + currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
System.out.println("MyThread was interrupted.");
return;
}
}
}
Running in main thread.
Hello from --- MyThread ---
Method 2: Implement the java.lang.Runnable interface and override the run() method
In this method, we create an instance of the class implementing the Runnable interface and pass it to the Thread() constructor.
public class Main {
public static void main(String[] args) {
System.out.println("Running in main thread.");
Thread myRunnableThread = new Thread(new MyRunnable());
myRunnableThread.start();
}
}
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Hello from MyRunnable's run() method");
}
}
Running in main thread.
Hello from MyRunnable's run() method
Method 3: Anonymous class overriding the run() method
public class Main {
public static void main(String[] args) {
System.out.println("Running in main thread.");
new Thread() {
@Override
public void run() {
System.out.println("Hello from the anonymous class run() method.");
}
}.start();
}
}
Running in main thread.
Hello from the anonymous class run() method.
Method 4: Anonymous implementation of Runnable interface
public class Main {
public static void main(String[] args) {
System.out.println("Running in main thread.");
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Hello from the anonymous Runnable implementation of run() method");
}
}).start();
}
}
Running in main thread.
Hello from the anonymous Runnable implementation of run() method
Gotchas
- Every thread created in a process shares the process memory and files which can lead to concurrency problems if not handled correctly. Each Thread has its own Thread stack that only that particular thread can access.
- A thread does not have to complete before another one starts unless we use something such as join() or interrupt() in Java or other ways to make a thread wait until another one completes execution. JVM decides when to schedule different threads to run.
Hope you learnt about the basics of Threads and some simplest ways of creating threads.
In the four methods that we saw above, threads should be instantiated and managed by developers manually. Oracle came up with a way of abstracting thread management using Executor API with its focus mainly on asynchronous processing rather than Thread management. This is a topic on its own, so let’s explore that in more detail in the next article along with synchronization of threads etc.

Love this website and articles!
LikeLiked by 1 person