AppDividend
Latest Code Tutorials

Java Multithreading Tutorial With Example | Multithreading in Java

0

Java Multithreading Tutorial With Example | Multithreading in Java is today’s topic. Usually, in a standard Java program, the entire program runs as a single “thread.” What it means that if a part of the program is demanding some I/O resource, for example, to proceed further, and if that I/O resource is not available at the moment, the entire program will be waiting and won’t also execute until and unless that particular resource in demand is freed. Multithreading in java is a process of implementing multiple threads simultaneously.

By definition, what multitasking is that when multiple processes share common processing resources such as a CPU. Multi-threading extends an idea of multitasking into applications where you can subdivide the specific operations within a single application into individual threads. Each of the threads can run in the parallel within the system. The OS divides the processing time not only among different applications but also among each thread within the application as well.

Multi-threading enables you to write in such a way where multiple activities can proceed concurrently in the same program.

As one can understand, this raises an issue in how fast the program gets executed. The address this issue, the concept of multithreading was developed wherein the program has multiple threads which can run in parallel.

What is Thread in Java

A thread is the lightweight sub-process, the smallest unit of processing. Multiprocessing and multithreading, both are used to achieve the multitasking. There can be multiple processes inside an OS, and one process can have multiple threads.

Multitasking

Multitasking is a process of executing multiple tasks simultaneously. We use multitasking to utilize the CPU. Multitasking can be achieved in two ways:

  • Process-based Multitasking (Multiprocessing)
  • Thread-based Multitasking (Multithreading)

1) Process-based Multitasking (Multiprocessing)

  • Each process has an address in memory. In other words, each process allocates a separate memory area.
  • A process is heavyweight.
  • Cost of communication between the process is high.
  • Switching from one process to another requires some time for saving and loading registers, memory maps, updating lists, etc.

2) Thread-based Multitasking (Multithreading)

  • Threads share the same address space.
  • A thread is lightweight.
  • Cost of communication between the thread is low.

Now, let’s see Java Multithreading Tutorial with example in deep.

Java Multithreading Tutorial

Java is the multi-threaded programming language which means we can develop a multi-threaded program using Java.

A multi-threaded program contains two or more parts that can run concurrently and each part can handle the different task at the same time making optimal use of the available resources, especially when your computer has multiple CPUs.

Life Cycle of a Thread

 

Life Cycle of a Thread

As shown in the above figure, a thread is executed inside a process. There is context-switching between the threads. There can be multiple processes inside the OS, and one process can have the multiple threads.

Following are the stages of the life cycle −

  • New − A new thread begins its life cycle in the new state. It remains in this state until a program starts the thread. It is also referred to as the born thread.
  • Runnable − After a newly born thread is started, the thread becomes runnable. The thread in this state is considered to be executing its task.
  • Waiting − Sometimes, a thread transitions to the waiting state while a thread waits for another thread to perform the task. Thread transitions back to the runnable state only when another thread signals the waiting thread to continue executing.
  • Timed Waiting − A runnable thread can enter the timed waiting state for the specified interval of time. A thread in this state transitions back to the runnable state when that time interval expires or when the event it is waiting for occurs.
  • Terminated (Dead) − A runnable thread enters the terminated state when it completes its task or otherwise terminates.

The Main Thread

When a Java program starts, one thread starts running – the main thread. The main thread is essential because this is the thread from which other child threads will be created and also because the main thread is often the last to finish execution as it generally performs various shutdown functions.

The main thread is created automatically when the program starts, and it can be controlled using a Thread object, as shown in the example below.

// MainThreadDemo.java

class MainThreadDemo{
	public static void main(String [] args){
		Thread t = Thread.currentThread();
		System.out.println("Main thread: " + t); 
		
                //now changing the name of the thread
		t.setName("New Name");
		System.out.println("Name changed to: " + t);
	}
}

OUTPUT

Java Multithreading Tutorial With Example

 

Here, the first println statement prints the name of the thread as “main,” which has priority “5”, and belongs to a group of threads called “main.”

By using the setName() method the name of the thread was changed to “New Name.”

Thread Priority

Every thread has a Thread Priority. If a thread is currently being executed in the CPU, and a thread of higher priority then demands the CPU, the thread with the lower priority will be preempted, and a context switch will happen, giving the CPU to the higher priority thread.

There is another way in which a thread can give up control. It is by voluntarily yielding, sleeping, or blocking on pending I/O.

Creating a Thread

In Java, there are two ways to create a thread.

  1. By implementing the Runnable interface
  2. By extending the Thread class

Implementing Runnable Thread

See the following code of SecondThread.java file.

// SecondThread.java

class SecondThread implements Runnable{
	Thread t;

	SecondThread(){
		t=new Thread(this, "Second Thread");
		System.out.println("Second Thread: " + t);
		t.start();

	}

	public void run(){
		try{
			for(int i=5; i>0; i--){
				System.out.println("Second Thread: " + i);
				Thread.sleep(1000);
			}
		}catch(InterruptedException e){
			System.out.println("Second interrupted.");
		}
		System.out.println("Exiting Second Thread");
	}
}

class RunnableDemo{
	public static void main(String [] args){
		new SecondThread();

		try{
			for(int i=5; i>0; i--){
				System.out.println("Main Thread: " + i);
				Thread.sleep(2000);
			}
		}catch(InterruptedException e){
			System.out.println("Main interrupted.");
		}
			
		
		System.out.println("Main thread exiting.");
	}
}

OUTPUT

Implementing Runnable Thread

 

The new thread is created by instantiating the SecondThread class. In the constructor of the SecondThread class, an instance of the Thread class is created having reference to the instance in which it is created (hence, the use of “this”).

The start() method calls the run() method which holds the actual content of the new thread. The second thread finishes execution when the run() method returns.

The method Thread.sleep(double milliseconds) is used to voluntarily let the thread sleep for the time entered in milliseconds as a parameter.

This method throws the InterruptedException, which is not handled by it, and hence, a try-catch mechanism has to be used every time this method is called.

As seen in the output, the second thread and the main thread execute simultaneously, with the second thread finishing first as it has been given less sleep time. The order of execution may vary from time to time.

Extending Thread

See the following example of ExtendingThread.java file.

// ExtendingThreadDemo.java

class SecondThread implements Runnable{
	Thread t;

	SecondThread(){
		t=new Thread(this, "Second Thread");
		System.out.println("Second Thread: " + t);
		t.start();

	}

	public void run(){
		try{
			for(int i=5; i>0; i--){
				System.out.println("Second Thread: " + i);
				Thread.sleep(1000);
			}
		}catch(InterruptedException e){
			System.out.println("Second interrupted.");
		}
		System.out.println("Exiting Second Thread");
	}
}

class RunnableDemo{
	public static void main(String [] args){
		new SecondThread();

		try{
			for(int i=5; i>0; i--){
				System.out.println("Main Thread: " + i);
				Thread.sleep(2000);
			}
		}catch(InterruptedException e){
			System.out.println("Main interrupted.");
		}
			
		
		System.out.println("Main thread exiting.");
	}
}

OUTPUT:

 

Extending Thread in Java

Here, the SecondThread class extends the Thread class, which is instantiated to create a new thread. In the constructor of SecondThread, super() is used to pass on the name of the second thread to the constructor of Thread.

The rest of the program executes like the example of implementing Runnable.

Advantages of Java Multithreading

1) It doesn’t block a user because threads are independent, and you can perform the multiple operations at the same time.

2) You can perform many operations together, so it saves time.

3) Threads are independent, so it doesn’t affect other threads if an exception occurs in a single thread.

Thus, Java multithreading solves the problem of programs being stuck due to resource allocation issues, and since Java itself handles a large part of the multithreading, the programming becomes easier to manage.

Thread Methods

Sr.No. Method & Description
1 public void start()

Starts a thread in the separate path of execution, then invokes a run() method on this Thread object.

2 public void run()

If this Thread object was instantiated using the separate Runnable target, the run() method is invoked on that Runnable object.

3 public final void setName(String name)

Changes the name of a Thread object. There is also a getName() method for retrieving a name.

4 public final void setPriority(int priority)

Sets a priority of this Thread object. The possible values are between 1 and 10.

5 public final void setDaemon(boolean on)

A parameter of true denotes this Thread as the daemon thread.

6 public final void join(long millisec)

The current thread invokes this method on the second thread, causing a current thread to block until a second thread terminates or the specified number of milliseconds passes.

7 public void interrupt()

Interrupts this thread, causing it to continue execution if it was blocked for any reason.

8 public final boolean isAlive()

Returns true if the thread is alive, which is any time after the thread has been started but before it runs to completion.

The previous methods are invoked on a particular Thread object. The following methods in the Thread class are static. Invoking one of the static methods operates on the currently running thread.

Sr.No. Method & Description
1 public static void yield()

Causes a currently running thread to yield to any other threads of the same priority that are waiting to be scheduled.

2 public static void sleep(long millisec)

Causes the currently running thread to block for at least the specified number of milliseconds.

3 public static boolean holdsLock(Object x)

Returns true if a current thread holds the lock on a given Object.

4 public static Thread currentThread()

Returns a reference to a currently running thread, which is a thread that invokes this method.

5 public static void dumpStack()

Prints the stack trace for the currently running thread, which is useful when debugging a multithreaded application.

Finally, Java Multithreading Tutorial With Example | Multithreading in Java article is over.

Leave A Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.