Threads In Java

Today, we will discuss Java Threads with examples, aim to satisfying the reader’s thirst for knowledge.

Java Threads

Using Java Threads, threads make it possible to run multiple processes simultaneously, increasing the efficiency of a program.

Complex tasks can be performed in the background without interfering with the main program using threads.



Create Java Thread

In order to create a thread in Java, there are two methods.

When dealing with Java Threads, it is created by overriding the run() method of the Thread class:

Syntax for Extend:

public class Main extends Thread {

    public void run(){
        System.out.println("We are learning about Java Threads");
    }
}

The Runnable interface can also be used to create a thread:

Syntax for Implement

public class Main implements Runnable {
    public void run(){
        System.out.println("A Java Threads can also be created by implementing the runable interface");
    }
}


Run Java Threads

Java Threads supports running threads by creating instances of classes that extend the Thread class and calling their start() method.

Extend Example:1 

public class Main extends Thread { public static void main(String[] args) { Main my_thread = new Main(); my_thread.start(); System.out.println("The code outside the thread will be executed from here"); } public void run() { System.out.println("The following code is a part of thread"); } }

Java Threads example

Extend Example:2 

public class Main extends Thread { public static void main(String[] args) { Main mrx_thread = new Main(); System.out.println("This contains the programme code"); mrx_thread.start(); // The arrangement does not matter as both thread and programme code runs side by side to each other } public void run() { System.out.println("This part is associated with a thread in order to run multiple commands at a time using the start method"); } }

Assuming that the class implements the Runnable interface, then the threadread can be executed by passing the class instance to the constructor of the Thread object and then calling the start() method of the thread object:

Implement Example:1 

public class Main implements Runnable { public static void main(String[] args) { Main mrx = new Main(); // Here we create an object of the Main class Thread ample_thread = new Thread(mrx); // The instance of ample_thread is created with the object of the Main class ample_thread.start(); // This calls the thread method System.out.println("The code in this section is outside the thread"); } public void run() { System.out.println("This code lies inside a thread"); } }

Implement Example:2 

public class Main implements Runnable { public static void main(String[] args) { Main mrx = new Main(); // Here we create an object of the Main class Thread ample_thread = new Thread(mrx); // The instance of ample_thread is created with the object of the Main class ample_thread.start(); // This calls the thread method System.out.println("The code for the addition of two integers is written inside the Main Method: "+(10+20)); } public void run() { System.out.println("Multiplication is done in a thread of the same numbers: "+(10*20)); } }

 

A noteworthy difference is that if a class extends the Thread class, it cannot extend anything else, but if it implements the Runnable interface, it may also extend from other classes, such as:


Concurrency Issue

There is no way to determine in what order code will run because threads run simultaneously with other parts of the program.

Variable values are unpredictable when threads and the main program read and write the same variables at the same time. Conflicts that result from this are termed concurrency Issues.

Here is an example of code, where the variable mrx has an unpredictable value:

Example: 

public class Main extends Thread { public static int mrx= 0;public static void main(String[] args) { Main thread = new Main(); thread.start(); System.out.println(mrx); // Show output as 0 mrx++; // The value of mrx becomes 1 System.out.println(mrx); // Prints 2 }public void run() { mrx++; // value of mrx becomes 2 here } }

The given example illustrates the difference in the value of variable ample while assigning the decrement operator and increment operator to it:

Example: 

public class Main extends Thread { public static int ample= 10;public static void main(String[] args) { Main thread = new Main(); thread.start(); System.out.println(ample); // Show output as 10 ample–; // The value of ample becomes 9 System.out.println(ample); // Prints 2 }public void run() { ample++; // value of ample becomes 10 again } }

The number of attributes that are shared between threads should be kept as low as possible in order to avoid concurrency problems.

The isAlive() method of the thread can be used to determine whether the thread has finished running before using any attributes it can modify.

This may be a solution if attributes need to be shared between threads.

Concurrency problems can be avoided by using isAlive() method:

isAlive() Example:1 

public class Main extends Thread { public static int mrx= 0;public static void main(String[] args) { Main mrx_thread = new Main(); mrx_thread.start();while (mrx_thread.isAlive()){ System.out.println("Waiting for the thread to complete the code execution"); } System.out.println(mrx); // Show output as 1 as the thread is utilized first mrx++; // The value of mrx becomes 2 System.out.println(mrx); // Prints 2 as the value is modified from 1 to 2 }public void run() { mrx++; // value of mrx becomes 1 here as thread runs first } }

isAlive Example:2 

public class Main extends Thread { public static int ample= 10;public static void main(String[] args) { Main mrx_thread = new Main(); mrx_thread.start(); while (mrx_thread.isAlive()){ System.out.println("Waiting for thread to execute first"); } System.out.println("Thread's value of ample: "+ample); // Show output as 11 as the run() method has incremented the value of ample ample–; // 1 is subtracted from the threads value System.out.println("Main Method value: "+ample); // Prints 10 as the value is decreased from 11 to 10 }public void run() { ample++; // value of ample is incremented to 11 here } }

Java Threads Benefits

Efficient Memory Consumption:

All threads within a process share the same address space. Hence, they do not use shared memory and multiple lines of code can be executed without consuming additional memory.

Best Utilization of Multiprocessor systems:

The use of threads enables a computer/laptop to utilize its multiprocessor architecture to a wider extent as multiple processors are indulged in the execution of multiple thread codes at a time.

We value your feedback.
+1
0
+1
0
+1
0
+1
0
+1
0
+1
0
+1
0

Subscribe To Our Newsletter
Enter your email to receive a weekly round-up of our best posts. Learn more!
icon

Leave a Reply

Your email address will not be published. Required fields are marked *