3 Ways to Create Thread in Java - onlyxcodes

Thursday 24 March 2022

3 Ways to Create Thread in Java

Hi, In this article you will learn 3 ways to create a thread in Java.


Threads help an application to work better by allowing it to do numerous tasks at once.


Threads enable complex activities to be completed in the background without affecting the program code.


This article not only discusses three methods for creating a thread in Java, but it also goes over the following topics:


Life Cycle of Thread in Java.


Thread Method in Java.


Multithreading in Java.


Creating Multiple Threads in Java.


Advantages and Disadvantages of Multithreading in Java.


Thread Synchronization in Java.


Thread Priority.


3 ways to create thread in java - how to create thread in java - creating multiple threads in java - multithreading in java - thread methods in java - runnable interface

Table Content

1. What is a Thread?

2. How to Create Thread in Java

3. Life Cycle of Thread in Java

4. Thread Methods in Java

5. Multithreading in Java

6. Thread Synchronization in Java

7. Thread Priority

8. Multitasking in Java


1. What is a Thread?

In Java, a thread is a route that a program takes once it is run. When the main() method is called with the main thread, the JVM (Java Virtual Machine) gives at least a single thread, known as the main thread, which is supplied by the JVM (Java Virtual Machine) at the beginning of the program's execution.


2. How to Create Thread in Java

Threads can be made in three different ways:


1. Extending the Thread class 


2. Implementing the Runnable Interface


3. Create Thread by Anonymous Class


1. Extending the Thread class 


The first approach is to make a class that extends Thread (java.lang.Thread).


The run() method of the Thread class is overridden by this class. This method serves as the thread's entry point, and it's where we'll place our simple logic.


Syntax of run() method:-


public void run()

Then, to begin thread execution, we define an object of our new class and use the start() method.


Syntax of start() method:


void start( );

The start() method on the Thread object calls the run() method.


class Test extends Thread
{
	public void run()
	{
		System.out.println("thread created successfully by extended thread class");
	}
	public static void main(String args[])
	{
		Test obj = new Test();
		obj.start();
	}
}

2. Implementing the Runnable Interface


The second step involves creating a new class that implements the Runnable interface (java.lang.Runnable interface) and overriding the run() method. Then we create a Thread object and call its start() method.


We'll define the for loop code for the new thread inside run().


Deliver an object of MyClass to a Thread's constructor to have it execute the run() method. 


Instead of running its run() method, the thread will call the run() method of the MyClass object when it is launched. The number "1 2 3" would be printed in the example.


class MyClass implements Runnable
{
	public void run()
	{
		for(int i=1; i<=3; i++)
		{
			System.out.println(i);
		}
	}
}
class Test
{
	public static void main(String args[])
	{
		MyClass obj = new MyClass();
		
		Thread t = new Thread(obj);
		t.start();
	}
}

3. Create Thread by Anonymous Class


The anonymous class can also be used to create a thread.


There are two ways to create an anonymous thread:-


  • By building an anonymous class that implements the Runnable interface as well as the run() method.

  • By extending the Thread class and overriding its run() method, an anonymous class is created.

1. By building an anonymous class that implements the Runnable interface as well as the run() method.


We'll create an object of an anonymous class that implements the Runnable interface and its run() method in this example.


Next, we provide the anonymous class's object to the Thread class's constructor because the Thread class's constructor requires a Runnable interface kind, and the anonymous class also becomes a Runnable type.


class Test 
{
	public static void main(String args[])
	{

		Runnable r = new Runnable() //Making an Anonymous class object which implements the Runnable interface
		{	 
			public void run() //Anonymous class that implements the Runnable class's run() method.
			{
				Thread t= Thread.currentThread();
				System.out.println("Thread Creating Successfully by Anonymous class which Implement Runnable Interface");

			}
		};

		Thread t= new Thread(r);  //Sending an anonymous class object to the Thread constructor
		t.start();	//The anonymous thread is being started.

		
	}
}

2. By extending the Thread class and overriding its run() method, an anonymous class is created.


We make an object of an anonymous class that has extended the Thread class and overridden its run() method in this example.


After that, we send an object of this anonymous class to the Thread class's reference, it is acceptable because a Thread reference can point to any of its subclasses' objects. An anonymous class in this example.


The anonymous thread is started by invoking the run() method of a method called t.start().


The System.out.println() statement is used in the run() method to display the thread that is creating the message.


class Test 
{
	public static void main(String args[])
	{
		Thread t= new Thread() //Establishing an Anonymous class object that extends Thread class and passing it to the Thread class's reference.
		{ 	
			public void run() //Anonymous class overrides the Thread class's run() method.
			{	
				System.out.println("Thread Creating Successfully by Anonymous class which extended Thread class");
			}
		};	//This is where the anonymous class finishes.
	
		t.start(); //Thread has been started anonymously.
	}
}

3. Life Cycle of Thread in Java

The thread's life cycle is classified into five stages that it can go through during its lifecycle. Each thread can be in one of the five states listed below.


Let's take a look at each of these different stages in the order they're listed below:-


life cycle of thread in java

1. New (New Born State) – Once we build a thread, it will be in a new state, referred to as the newborn state.


When the thread is in this state, it not yet begins to run. The start() method can be used to put it into running mode.


2. Runnable State – A newly created thread becomes runnable once it can begin. When a thread is in this state, it is recognized to be in the beginning of its process. The run() method can be used to start a thread in running mode.


3. Running State – The thread is ready to execute in this state since it has been given control of the CPU.


A processor in the running state provides the thread its time for processing and executes the thread's run method. This is the state in which the thread executes its tasks. Only a runnable state allows a thread to enter the running state.


For various reasons, a running thread can gain control and enter the blocked state by using the sleep(), suspend(), or wait() methods.


  • sleep() – Once the sleep() method is called on a thread to put it to sleep for a certain amount of time, the thread is taken out of the queues for that amount of time. As soon as this time duration expires, the thread reenters the runnable state.

  • suspend() – If a thread is paused for an amount of time using the suspend() method to meet certain conditions. The resume() method can be used to restart a suspended thread.

  • wait() – Once the wait() method on a thread is used to wait for a certain amount of time. The notify() or notifyAll() methods can be used to restart a thread in the wait state.

4. Blocked State –  If a thread is suspended, sleeping, or waiting for some time to fulfill a few requirements, it is regarded to be in the blocked state.


5. Dead State – When a thread's run() method completes the execution of statements, it automatically switches into this state.


When the stop() method is called, a thread can also be destroyed.


4. Thread Methods in Java

On a Thread class object, we have several methods that can be invoked. When creating multithreaded programs, these methods come in useful. The Thread class contains the following useful methods.


start() – The thread is started.


getState() – Its returns the thread's current status.


getName() – This gives the thread's name.


getPriority() – That returns the thread's priority.


sleep() – Pause the thread for the amount of time supplied.


Join() – Stop the current thread and wait for the called thread to finish.


isAlive() – Verify to see if the thread is still active.


5. Multithreading in Java

The basic concept of thread in Java was covered in the previous section. Now we'll look at some examples of multithreading in Java.


One of Java's most powerful features is its multithreading programming technique. It boosts performance while also making our program more flexible and engaging.


What is Multithreading in Java?


Multithreading refers to the execution of many threads at the same time. Multithreading is the term used in Java to describe the process of running many threads at the same time.


Multithreading, in other words, is a programming concept in which a program is divided into two or more modules, that can all perform multiple tasks at the same time. In Java, every program's subprogram is referred to as a thread.


Creating Multiple Threads in Java


class Car implements Runnable
{
	public void run()
	{
		int i=10;
		System.out.println("value i =" +i);
	}
}

class Bike implements Runnable
{
	public void run()
	{
		int j=20;
		System.out.println("value j =" +j);
	}
}

class Test
{
	public static void main(String args[])
	{
		Car obj = new Car();
		Bike obj1 = new Bike();
		
		Thread t = new Thread(obj);
		t.start();
		
		Thread t1 = new Thread(obj1);
		
		try
		{
			t1.sleep(3000);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		t1.start();
	}
}

Explanation:


To begin, make a "Car" class that implements the Runnable interface and overrides the run() method.


We declare an integer type i variable with a value of 10 inside the run() method.


The i value is printed using the System.out.println() statement.


class Car implements Runnable
{
	public void run()
	{
		int i=10;
		System.out.println("value i =" +i);
	}
}

Second, make a "Bike" class that implements the Runnable interface and overrides the run() method.


We declare an integer type j variable with a value of 20 inside the run() method.


The j value is printed using the System.out.println() statement.


class Bike implements Runnable
{
	public void run()
	{
		int j=20;
		System.out.println("value j =" +j);
	}
}

Create a main class called the "Test" after that. We make both car and bike class objects in the main method.


The car class object is "obj," while the bike class object is "obj1."


Next, we build a Thread class object called t, and we pass a car class object called "obj" to this thread class.


To execute the thread of the car class, we used the start() method of the Thread class object "t."


Next, we create a second Thread class object called "t1," and we send a car class object called "obj1" to this thread class.


We used the "t1" object to call the sleep() method before calling the start() method within the try/catch block. After 3 seconds, this method displays the output of the bike class.


To execute the thread of the bike class, we use the start() method of the second thread class object "t1."


class Test
{
	public static void main(String args[])
	{
		Car obj = new Car();
		Bike obj1 = new Bike();
		
		Thread t = new Thread(obj);
		t.start();
		
		Thread t1 = new Thread(obj1);
		
		try
		{
			t1.sleep(3000);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		t1.start();
	}
}

Advantages of Multithreading in Java


1. In a multithreaded application program, separate threads execute various parts of the application. Even if one of the threads throws an exception, the entire application does not quit. During the application's execution, it does not affect other threads.


2. Different threads are assigned to different processors, and each thread is run in parallel by multiple processors.


3. Multithreading assists in the speed-up of operations.


4. Multithreading grows the application's performance.


5. Threads sharing the same addressing space in memory. As a result, it preserves memory.


6. A multithreaded application utilizes the CPU to its best ability while minimizing CPU inactive time.


7. Switching between threads is less costly than moving between processes.


Disadvantages of Multithreading in Java


1. A higher level of complexity.


2. Testing a multithreaded application is more challenging than testing a single-threaded application because timing-related issues are more difficult to reproduce.


3. The possibility of deadlock increases.


4. The difficulty of writing a program increases.


5. Unexpected outcomes.


6. Thread Synchronization in Java

Multiple threads attempt to enter shared resources at the same time in the Multithreading program, resulting in different outcomes. Synchronization is required for thread interaction to be effective.


Synchronization is the process of managing multiple thread requirements for resource accessibility. Synchronization's basic aim is to stop thread disruption.


When multiple threads attempt to access a shared resource, we must ensure that the resource is only accessed by one thread at a time. Synchronization is the method by which this is accomplished.


The java keyword "synchronized" can be used to accomplish Thread Synchronization.


Types of Synchronization


In Java, there are two types of synchronization. They are as follows:


1. Process Synchronization


2. Thread Synchronization


1. Process Synchronization


Process synchronization is a word that refers to sharing resources between two or more processes while maintaining data consistency.


2. Thread Synchronization


There are two types of thread synchronization:


1. Mutual Exclusive.


2. Cooperation (Inter Thread communication in Java)


1. Mutual Exclusive


Only one thread can access the shared resources due to Mutual Exclusive. This won't let you access shared resources at the same time. It can be done in a variety of ways.


  • Synchronized Method

  • Synchronized block

  • Static Synchronization

Understanding the Lock in Java 


The monitor, also known as a lock, is an internal component that is attached to each object. As a result, if a thread tries to access an object, it must first obtain the object's lock, act on the object, and then release the lock.


The Issue without Synchronization


Program with no Synchronization,


We are not using synchronization in this program, instead of creating multiple threads that access the run() method and produce incorrect output.


class Car implements Runnable
{
	public void run()
	{
		for(int i=1; i<=4; i++)
		{
			System.out.println("value=" +i);	
		}
		
	}
}

class Test
{
	public static void main(String args[])
	{
		Car obj = new Car();
		

		Thread t1 = new Thread(obj);
		Thread t2 = new Thread(obj);
		Thread t3 = new Thread(obj);
		
		t1.start();
		t2.start();
		t3.start();
	}
}

Output:


As a result, the result is incorrect.


value=1
value=2
value=3
value=4
value=1
value=2
value=1
value=3
value=2
value=4
value=3
value=4

Synchronized Method:


Any method that has the Synchronized keywords declared is a Synchronized Method.


Thread interruption and memory stability issues can be avoided with the use of synchronized methods.


If an object is visible to multiple threads, the synchronized method is used for all reading and writing to that object's properties.


Program with Synchronized


We use the "synchronized" keyword before the run() method in this example to synchronize many threads and produce the correct output.


The keyword "synchronized" can be used before the run() method to synchronize multiple threads.


class Car implements Runnable
{
	public synchronized void run()
	{
		for(int i=1; i<=4; i++)
		{
			System.out.println("value=" +i);	
		}
		
	}
}

class Test
{
	public static void main(String args[])
	{
		Car obj = new Car();
		
		Thread t1 = new Thread(obj);
		Thread t2 = new Thread(obj);
		Thread t3 = new Thread(obj);
		
		t1.start();
		t2.start();
		t3.start();
	}
}

Output:


After we've used the synchronized keyword, have a look at the proper output display.


value=1
value=2
value=3
value=4
value=1
value=2
value=3
value=4
value=1
value=2
value=3
value=4

Synchronized block:


If you only want to synchronize a few lines of code in a method and don't want to synchronize the entire method, a synchronized block can help.


The object will be passed as an argument. It will act similarly to the Synchronized Method. When using a synchronized method, the lock is accessible on the method, but when using a synchronized block, the lock is accessible on the object.


class Counter 
{ 
    public void counterIncrement() 
    { 
        synchronized(this)
        {
			System.out.println("The output of synchronized block is: ");
			
            for (int i = 1; i <= 3; i++) 
            { 
                System.out.println(i); 
				
                try 
                { 
                    Thread.sleep(1000); 
                } 
                catch (Exception e) 
                { 
                    System.out.println(e); 
                } 
            } 
        }
    } 
} 
  
class MyThread extends Thread { 
   
    Counter cnt; 
  
    MyThread (Counter cnt) { 
        this.cnt = cnt; 
    } 
  
    public void run() { 
        cnt.counterIncrement(); 
    } 
} 
  
class Test
{ 
    public static void main(String[] args) 
    { 
        Counter obj = new Counter(); 
  
        MyThread t1 = new MyThread(obj); 
        MyThread t2 = new MyThread(obj); 
  
        t1.start(); 
        t2.start(); 
    } 
}

Output:


The output of synchronized block is:
1
2
3
The output of synchronized block is:
1
2
3

Explanation:


Two threads, t1 and t2, are utilized in the above program, with each having a counterIncrement() method that calls the synchronized method.


The output of the synchronized block of the first thread, as seen in the result, is 1, 2, 3. The outcome of the thread's second synchronized block is also 1, 2, 3 at the same time.


In addition, between each thread's result comes a line that says "The output of the synchronized block is."


Static Methods Synchronization:


Each object in Java has a single lock (monitor) attached to it. That lock will be given to the thread that enters the synchronized method or synchronized block.


All other threads that need to utilize the shared resources wait for the first thread to finish and the lock to be released.


If we have more than one object, two independent threads will obtain the locks and enter a synchronized block or synchronized method at the same time, with a different lock for every object. We'll utilize static synchronization to solve this.


Instead of using an instance method, we utilize a static method to print numbers from 1 to 3.


class Counter
{
    public static synchronized void countNumber()
    {
        for (int i = 1; i <= 3; i++)
        {
			System.out.println(Thread.currentThread().getName() + ": " + i);
            try
            {
                Thread.sleep(200);
            }
            catch (InterruptedException e)
            {
                System.out.println(e);
            }
        }
    }
}
  
class MyRunnable implements Runnable
{ 
    @Override
    public void run()
    {
        Counter.countNumber();
    }
}
  
class Test
{
    public static void main(String[] args)
    {
        
        Runnable obj = new MyRunnable();
        
        Thread t1 = new Thread(obj);
        Thread t2 = new Thread(obj);
        
        t1.start();
        t2.start();
    }
}

Explanation:


First, we created the Counter class. 


The method is declared as static and synchronized in this example.


Next, we create MyRunnable, a new class that implements the Runnable interface (java.lang.Runnable interface) and overrides the run() method.


Because countNumber() is a static method, MyRunnable calls it directly using the class name.


Finally, the main class has been created.


The main method also creates two threads, t1 and t2, with the MyRunnable parameter and starts them.


Output:


We can see that each thread finishes printing from 1 to 3 before moving on to the next.


The lock is kept by the Counter class in the case of static methods.


Thread-0: 1
Thread-0: 2
Thread-0: 3
Thread-1: 1
Thread-1: 2
Thread-1: 3

2. Cooperation (Inter Thread communication in Java)


Cooperation (inter-thread communication) is a technique where a thread is stopped in its necessary part while another thread accesses (or locks) the same necessary area to be run. The following methods of the Object class are used to accomplish it.


  • wait()

  • notify()

  • notifyAll()

1) wait() Method:


The wait() method tells the current thread to leave the lock and wait when another thread calls the notify() or notifyAll() methods for this object, or until a certain time has passed.


This object's watch must be owned by the current thread, therefore it can only be called from the synchronized method; otherwise, it will throw an error.


2) notify() Method:


The notify() method starts a single thread that waits on the watch of an object. If one object has any waiting threads, one of them is picked to be activated. The decision is subjective and made at the implementation's judgment.


Syntax:


public final void notify() 


3) notifyAll() Method:


The watcher of an object wakes up all waiting threads.


Syntax:


public final void notifyAll() 


7. Thread Priority

There is a priority for each thread. Priorities are assigned a number between one and ten. The thread scheduler, like most instances, schedules threads according to their priority.


However, it is not assured because the scheduling option used by the JVM is dependent on the JVM configuration. It's worth noting that, in addition to the JVM, a Java programmer can directly designate thread priority in a Java program.


setPriority:- This method is used to set the priority.


getPriority:- This method is used to get the priority.


In thread classes, the three constants and their default values are used.


MIN_PRIORITY – 1


NORM_PRIORITY – 5


MAX_PRIORITY – 10


Example:


We assign constants to the two classes and receive their values in this example.


class A extends Thread
{
	public void run()
	{
		System.out.println("A class call");	
	}
}
class B extends Thread
{
	public void run()
	{
		System.out.println("B class call");
	}
}

class Test
{
	public static void main(String args[])
	{
		A obj = new A();
		B obj1 = new B();
		
		obj.setPriority(Thread.MIN_PRIORITY);
		System.out.println("A class priority is = " +obj.getPriority());
		
		obj1.setPriority(Thread.MAX_PRIORITY);
		System.out.println("B class priority is = " +obj1.getPriority());
		
		obj.start();
		obj1.start();
	}
}

Output:


A class priority is = 1
B class priority is = 10
A class call
B class call

Explanation:


Above the program, we created two classes A and B. Both classes extend the Thread class and override the Thread class's run() method.


The main class, Test, was then created. We created both A and B class objects in the main method.


The object of the A class is obj, while the object of the B class is obj1.


The setPriority() method on the obj object is used to set the priority of the A class. And a value of 1 for MIN_PRIORITY assigned.


The class is printed using the System.out.println() statement. The getPriority() method returns a priority.


The setPriority() method on the obj1 object is used to set the priority of the B class. And a value of 10 is assigned to MAX_PRIORITY.


The getPriority() method in the System.out.println() statement prints the class B priority.


8. Multitasking in Java

Multitasking is the process of performing multiple tasks simultaneously or at the same time. That is an operating system's capacity to perform numerous tasks at the same time. The primary goal of multitasking is to take advantage of a CPU's inactive time.


There are two techniques for multitasking:


  • Process-based multitasking (Multiprocessing)

  • Thread-based multitasking (Multithreading)

Process-based multitasking (Multiprocessing)


Process-based multitasking is the process of running many applications or processes at the same time simultaneously. The microprocessor executes numerous programs simultaneously in process-based multitasking.


As a result, it's also known as multiprocessing in Java. It's a big package. Process-based multitasking enables users to access two or more applications on the computer at the same time.


Running an excel spreadsheet while also using a text editor is a nice illustration.


Each process has its memory location range. In other words, each application is given its own memory space.


To move from one program to another, the operating system takes some CPU time. Background switching is the process of moving the CPU between processes.


The transition from one application to the next happens so quickly that the user thinks numerous tasks are being completed at the same time.


Thread-based Multitasking (Multithreading)


For each task within a program, a thread is a separate direction of code execution. A program includes many threads to do one or more activities at the same time by a processor in thread-based multitasking.


That is, thread-based multitasking allows you to run many elements of the same application at the same time. Each thread follows a different execution route.


Thread-based multitasking has several advantages compared to process-based multitasking. Few are listed below.


1. Threads share the same location area in memory.


2. Background shifting across threads is less expensive than moving between processes.


3. The cost of thread-to-thread communication is quite cheap.


4. When compared to processes, threads are light. They make use of all the system's resources. They use less memory and time on the processor.


5. Java enables thread-based multitasking and offers a high level of multithreading programming capabilities.


6. A good way to remember the difference between process-based and thread-based multitasking is that process-based multitasking works with numerous programs or processes, whereas thread-based multitasking works with components of a single program.


7. A program is the smallest element of executable code in process-based multitasking, whereas a thread is the smallest element of executable code in thread-based multitasking.


Frequently Asked Questions

Why Do We Need Synchronization in Thread?


Synchronization is required when multiple processes need to run at the same time. This is because we require resources that may be shared across multiple processes.


We need to synchronize these resources to minimize conflicts between processes or threads for accessing shared resources so that all threads have access to resources and the application proper consideration.


What is Multitasking vs Multithread?


Multitasking: Fulfills a variety of things


Multithread: Executes many threads at once


Multitasking: All process has their own set of resources and memory.


Multithread: The memory and resource pool for all threads is the same.


Multitasking: Between tasks, the CPU background switches.


Multithread: Between threads, the CPU background switches.


Multitasking: When compared to multithreading, performance is slow.


Multithread: When compared to multitasking, performance is faster.


What is Thread vs Process?


Thread: Threads are more lightweight operations.


Process: Processes are heavy operations.


Thread: Threads rely on the memory of the process to which they belong.


Process: Each process has its dedicated memory.


Thread: Because threads belonging to the same process share memory, inter-thread communication can be faster than inter-process communication.


Process: Because processes have distinct memory addresses, inter-process communication is slow.


Thread: It is less expensive to move environments between threads of the same process.


Process: Moving between processes in a different environment is more expensive.


Thread: Threads in the same process exchange memory with one another.


Process: Processes do not exchange memory with each other.

No comments:

Post a Comment

Post Bottom Ad