What are Threads in Java ?

Kajal Rawal
4 min readDec 21, 2020

What is a Thread ?

Thread is the path of execution in application. Applications can have multiple threads which are executed in parallel. In Java, threads are instances of java.lang.Thread class or subclasses which extend the Thread class. Every thread has priority (min. 1, max. 10) which is used by Thread Scheduler to determine the priority of execution. Also, a new created thread has an initial priority set from the creating thread (parent thread).

The main thread is a single non-daemon thread that is started by JVM to execute the main method. Default priority of the main thread is 5.

public static void main(String[] args) {
Thread mainThread = Thread.currentThread();
System.out.println("Name: " + mainThread.getName());
System.out.println("Priority: " + mainThread.getPriority());
System.out.println("Group: " + mainThread.getThreadGroup().getName());
}
Console output:
Name: main
Priority: 5
Group: main

Each thread in a Java creates its own stack. Size of the stack by default is 512KB to 1024KB and it can be changed using JVM command -Xss.

What is difference between Process and Thread ?

Thread is a segment of the process, a single process can have multiple threads. Threads are lightweight and they are run in shared memory space inside the process which provides easier inter thread communication between threads.

Main Thread in Java

Thread and Runnable in Java

Thread class implements a Runnable interface which has only a run method. The Runnable's run method should be implemented in order to be executed by thread.

The following code shows one of the ways Runnable interface can be implemented and executed by the thread.

Runnable runnable = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("i: " + i);
}
}
};
Thread thread = new Thread(runnable);
thread.start();

Thread States

Java Thread.State has six states: NEW, RUNNING, BLOCKED, WAITING, TIMED_WAITING and TERMINATED.

  • NEW — Thread has been created but it is not started
  • RUNNING — Thread is executing in JVM
  • BLOCKED — Thread is being blocked and waiting for monitor to continue execution
  • WAITING — Thread is waiting indefinitely for another thread to perform action
  • TIMED_WAITING — Similar as waiting state but in this case waiting time is specified
  • TERMINATED — Thread has been exited

All those states are part of the Thread.State Enum class. Thread state can be checked by calling thread.getState() methods.

Race Condition

A race condition occurs when two or more threads access shared data and try to read and write at the same time.

The following code example shows race condition

public static void main(String[] args) {
Runnable runnable = new Runnable() {
private int counter = 0;
@Override
public void run() {
while (true) {
counter++;
String threadName = Thread.currentThread().getName();
System.out.println(threadName + ", value: " + counter);
counter--;
System.out.println(threadName + ", value: " + counter);
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
}
}
};
Thread threadA = new Thread(runnable);
threadA.setName("Thread A");
threadA.setDaemon(false);
threadA.setPriority(5);
Thread threadB = new Thread(runnable);
threadB.setName("Thread B");
threadB.setDaemon(false);
threadB.setPriority(5);
threadA.start();
threadB.start();
}

Both threads execute the same instance of Runnable and change Int variable counter. Since there is no synchronize block, output of this code looks like:

Console output:
Thread A, value: 0
Thread B, value: 1
Thread B, value: 0
Thread A, value: 1
Thread A, value: -1
Thread B, value: 0
Thread B, value: -1
Thread A, value: 0
Thread A, value: -2

We can fix race condition by adding synchronization block:

public void run() {
while (true) {
synchronized (this) {
counter++;
String threadName = Thread.currentThread().getName();
System.out.println(threadName + ", value: " + value);
counter--;
System.out.println(threadName + ", value: " + value);
}
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
}
}

So, I put a synchronized block and lock it by using a monitor from an instance of Runnable. Since both threads use the same instance of Runnable this monitor will prevent my threads A and B from accessing the block of code at the same time.

Output of the fixed code:

Console output:
Thread A, value: 1
Thread A, value: 0
Thread B, value: 1
Thread B, value: 0
Thread A, value: 1
Thread A, value: 0

What is Deadlock

The deadlock situation occurs when the first thread holds a key needed by the second thread and the second thread holds a key needed by the first thread.

The good thing is that JVM can detect deadlocks and log the information.

Example of deadlock:

private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
public static void main(String[] args) {
Thread threadA = new Thread(() -> {
synchronized (lock1) {
System.out.println("first lock is called");
synchronized (lock2) {
System.out.println("second lock is called");
}
}
});
Thread threadB = new Thread(() -> {
synchronized (lock2) {
System.out.println("second lock is called");
synchronized (lock1) {
System.out.println("first lock is called");
}
}
});
threadA.start();
threadB.start();
}

What’s the right way to stop the Thread ?

Thread is automatically stopped when the run method has completed, but sometimes we need to stop/cancel it before the run method ends. The right way to stop the thread is by calling the interrupt method and checking from time to time what is the result of the isInterrupted.

Methods suspend(), resume() and stop() are deprecated and it is not recommended to use them.

--

--

Kajal Rawal

Programming isn’t about what you know; it’s about what you can figure out.