Java Threads
Threads allows a program to operate more efficiently by doing multiple things at the same time.
Threads can be used to perform complicated tasks in the background without interrupting the main
program.
Creating a Thread
There are two ways to create a thread.
It can be created by extending the Thread class and overriding its run() method:
Extend SyntaxGet your own Java Server
public class Main extends Thread {
public void run() {
[Link]("This code is running in a thread");
Another way to create a thread is to implement the Runnable interface:
Implement Syntax
public class Main implements Runnable {
public void run() {
[Link]("This code is running in a thread");
Running Threads
If the class extends the Thread class, the thread can be run by creating an instance of the class and
call its start() method:
Extend Example
public class Main extends Thread {
public static void main(String[] args) {
Main thread = new Main();
[Link]();
[Link]("This code is outside of the thread");
public void run() {
[Link]("This code is running in a thread");
If the class implements the Runnable interface, the thread can be run by passing an instance of the
class to a Thread object's constructor and then calling the thread's start() method:
Implement Example
public class Main implements Runnable {
public static void main(String[] args) {
Main obj = new Main();
Thread thread = new Thread(obj);
[Link]();
[Link]("This code is outside of the thread");
public void run() {
[Link]("This code is running in a thread");
}
Multithreading in Java is a programming feature that allows for the concurrent execution of multiple
parts of a program, known as threads. This enables a single program to perform multiple tasks
simultaneously, leading to improved performance, responsiveness, and CPU utilization, especially in
applications that involve computationally intensive operations or waiting for external resources.
Thread:
A thread is a lightweight sub-process, representing the smallest unit of processing that can be scheduled and
executed independently within a larger program. Threads within the same process share the same memory
space.
Concurrency:
The ability of a system to handle multiple tasks or threads seemingly at the same time, even if they are not truly
executing in parallel (e.g., on a single-core CPU, time-slicing gives the illusion of concurrency).
Parallelism:
The true simultaneous execution of multiple tasks or threads on a multi-core CPU or system with multiple
processors.
class CookingTask extends Thread {
private String task;
CookingTask(String task) {
[Link] = task;
public void run() {
[Link](task + " is being prepared by " +
[Link]().getName());
public class Restaurant {
public static void main(String[] args) {
Thread t1 = new CookingTask("Pasta");
Thread t2 = new CookingTask("Salad");
Thread t3 = new CookingTask("Dessert");
Thread t4 = new CookingTask("Rice");
[Link]();
[Link]();
[Link]();
[Link]();
Differences between "extending" and "implementing" Threads
The major difference is that when a class extends the Thread class, you cannot extend any other
class, but by implementing the Runnable interface, it is possible to extend from another class as
well, like: class MyClass extends OtherClass implements Runnable.
Concurrency Problems
Because threads run at the same time as other parts of the program, there is no way to know in
which order the code will run. When the threads and main program are reading and writing the
same variables, the values are unpredictable. The problems that result from this are called
concurrency problems.
Example
A code example where the value of the variable amount is unpredictable:
public class Main extends Thread {
public static int amount = 0;
public static void main(String[] args) {
Main thread = new Main();
[Link]();
[Link](amount);
amount++;
[Link](amount);
public void run() {
amount++;
To avoid concurrency problems, it is best to share as few attributes between threads as possible. If
attributes need to be shared, one possible solution is to use the isAlive() method of the thread to
check whether the thread has finished running before using any attributes that the thread can
change.
Example
Use isAlive() to prevent concurrency problems:
public class Main extends Thread {
public static int amount = 0;
public static void main(String[] args) {
Main thread = new Main();
[Link]();
// Wait for the thread to finish
while([Link]()) {
[Link]("Waiting...");
// Update amount and print its value
[Link]("Main: " + amount);
amount++;
[Link]("Main: " + amount);
public void run() {
amount++;
}
Every Java thread has a priority that helps the operating system determine the order in
which threads are scheduled. You can get and set the priority of a Thread. Thread class provides
methods and constants for working with the priorities of a Thread.
Threads with higher priority are more important to a program and should be allocated processor
time before lower-priority threads. However, thread priorities cannot guarantee the order in which
threads execute and are very much platform dependent.
Built-in Property Constants of Thread Class
Java thread priorities are in the range between MIN_PRIORITY (a constant of 1) and MAX_PRIORITY
(a constant of 10). By default, every thread is given priority NORM_PRIORITY (a constant of 5).
MIN_PRIORITY: Specifies the minimum priority that a thread can have.
NORM_PRIORITY: Specifies the default priority that a thread is assigned.
MAX_PRIORITY: Specifies the maximum priority that a thread can have.
Thread Priority Setter and Getter Methods
[Link]() Method : This method is used to get the priority of a thread.
[Link]() Method : This method is used to set the priority of a thread, it accepts the
priority value and updates an existing priority with the given priority.
package [Link];
class ThreadDemo extends Thread { ThreadDemo( )
{ } public void run() { [Link]("Thread Name: " +
[Link]().getName() + ", Thread Priority: "
+[Link]().getPriority()); for(int i = 4; i > 0; i--) {
[Link]("Thread: " + [Link]().getName() + ", " + i); } try {
[Link](50); } catch (InterruptedException e) { // TODO Auto-generated catch
block [Link](); } } public void start () { [Link](); } } public class
TestThread { public static void main(String args[]) { ThreadDemo thread1 = new
ThreadDemo(); ThreadDemo thread2 = new ThreadDemo(); ThreadDemo thread3 = new
ThreadDemo(); [Link](Thread.MAX_PRIORITY);
[Link](Thread.MIN_PRIORITY); [Link](Thread.NORM_PRIORITY);
[Link](); [Link](); [Link](); } }
Thread Synchronization in Java
Java programming language provides a very handy way of creating threads and synchronizing their
task by using synchronized blocks. You keep shared resources within this block. Following is the
general form of the synchronized statement −
Syntax
synchronized(objectidentifier) { // Access shared variables and other shared
resources }
Multithreading Example without Thread Synchronization
Here is a simple example which may or may not print counter value in sequence and every time we
run it, it produces a different result based on CPU availability to a thread.
class PrintDemo { public void printCount() { try { for(int i = 5; i > 0; i--) {
[Link]("Counter --- " + i ); } } catch (Exception e) {
[Link]("Thread interrupted."); } } } class ThreadDemo extends Thread {
private Thread t; private String threadName; PrintDemo PD; ThreadDemo( String name,
PrintDemo pd) { threadName = name; PD = pd; } public void run() { [Link]();
[Link]("Thread " + threadName + " exiting."); } public void start () {
[Link]("Starting " + threadName ); if (t == null) { t = new Thread
(this, threadName); [Link] (); } } } public class TestThread { public static void
main(String args[]) { PrintDemo PD = new PrintDemo(); ThreadDemo T1 = new
ThreadDemo( "Thread - 1 ", PD ); ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD
); [Link](); [Link](); // wait for threads to end try { [Link](); [Link](); }
catch ( Exception e) { [Link]("Interrupted"); } } }
This produces a different result every time you run this program −
Output
Starting Thread - 1
Starting Thread - 2
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 5
Counter --- 2
Counter --- 1
Counter --- 4
Thread Thread - 1 exiting.
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread - 2 exiting.
Multithreading Example with Thread Synchronization
Here is the same example which prints counter value in sequence and every time we run it, it
produces the same result.
class PrintDemo { public void printCount() { try { for(int i = 5; i > 0; i--) {
[Link]("Counter --- " + i ); } } catch (Exception e) {
[Link]("Thread interrupted."); } } } class ThreadDemo extends Thread {
private Thread t; private String threadName; PrintDemo PD; ThreadDemo( String name,
PrintDemo pd) { threadName = name; PD = pd; } public void run() { synchronized(PD)
{ [Link](); } [Link]("Thread " + threadName + " exiting."); }
public void start () { [Link]("Starting " + threadName ); if (t ==
null) { t = new Thread (this, threadName); [Link] (); } } } public class
TestThread { public static void main(String args[]) { PrintDemo PD = new
PrintDemo(); ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD ); ThreadDemo T2 =
new ThreadDemo( "Thread - 2 ", PD ); [Link](); [Link](); // wait for threads to
end try { [Link](); [Link](); } catch ( Exception e) {
[Link]("Interrupted"); } } }
This produces the same result every time you run this program −
Output
Starting Thread - 1
Starting Thread - 2
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread - 1 exiting.
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread - 2 exiting.