Java Thread: One of the dominant features of the Java language is that it provides built-in support for multithreading – the concurrent running of multiple threads within the same program. Creating a thread in Java is relatively easy. Unlike the old fashioned programming languages, where you have to invoke system-dependent procedures and functions to implement multithreading, in Java, it is no harder than creating an instance of other classes.
The programs that we have written so far had only one entry point (main() method) and one exit point. All the instructions in these programs executed serially one at a time beginning at the first statement in main () and continuing sequentially through the statements until the program ends. This single sequence of executable statements within a program is known as a thread. In other words, a thread is s flow of execution of a task in a program, so it is known as a thread of execution or a thread of control.
We’ll be covering the following topics in this tutorial:
Explanation of Threads in java
In real life situations, it may be possible that a program needs to perform multiple tasks at the same time. Some of the examples are
• A word processor application can automatically check your spelling and grammar while it allows you to perform some other tasks such as entering the text.
• Email programs download the messages and at the same time allow you to read the messages.
• A program is capable of downloading data from the network while responding to mouse or keyboard input from the user.
• A word processor application can print long documents in the background while allowing you to continue your work.
• Web browsers can download files while still letting you view web pages.
From the above examples, we observe that multiple tasks are performed concurrently (i.e., at the same time) within the same program. The above examples cause problems when solved using the single-threaded program. For example, A single thread is not capable of responding to mouse or keyboard input from the user while downloading data from the network. It is because it must give its full attention to either the keyboard input or the network download. The ideal solution to this problem is the execution of two or more sections of a program at the same time. It is possible using the concept of multithreading. The multithreading applications are capable of running multiple tasks concurrently within a single program rather than waiting for one task to finish before others can start. Each thread has its sequence of statements, and within each thread, the statements are executed one after the other as usual. However, by alternatively executing the statements from one thread and another, the computer can run multiple threads concurrently. Even though CPU executes one statement at a time, it can run multiple threads concurrently by rapidly switching among them. So when the above example uses multiple threads, one thread can easily download data from the network, and other thread can respond to mouse or keyboard input from the user. The advantage of multithreading is that it utilizes system resources (like CPU) efficiently because other threads can grasp CPU time while one thread of execution blocked. Thus, it makes the program more responsive, interactive and enhance performance.
One can correlate the concept of threads with the concept of time-sharing. With time-sharing, the computer seems to be running several different programs (or applications) simultaneously even though it can run only one program at a time. For example, You can open a text editor and a web browser and work with both of them at the same time. The operating system makes this possible by running one program for a short duration of time then switching to the second program, then to the third program and then switching back to the first program and so on. Threads extend this concept of switching among several different programs to switching among different threads (processes) in the same program. Several threads may be running concurrently in a program, each in its thread of execution control.
Creating Threads in Java
When a Java program begins execution, it always has at least one thread, i.e., the main thread. In typical Java application program, this thread starts at the beginning of main () method that means that when your program creates a thread, it is in addition to the main thread of execution that created it. Java provides two ways to make your class behave like a thread.
• By extending a java.lang.Thread class and override its run() method
• By implementing the Runnable interface and implementing its run() method
Now the question arises which of the two thread creating techniques one should use. The first technique can only use for classes that do not already extend any other class. Therefore, we stick with the second approach which is always applicable.
Before creating a class that extends the Thread class, you need to understand the java.lang.Thread class. The Thread class lets you create an object that can run as a thread in a multithreaded Java application. It is a direct subclass of an object class, and it implements the Runnable interface. A Thread object controls a thread running under the JVM. The Thread class contains the following constructors for creating threads and methods for controlling threads.
Creating Thread Using Thread Class
You can make your class to behave as a thread by defining your class as a subclass of java.lang. Thread class and overriding its run () method which is the entry point for the new thread. This method contains the code that will be executed when the thread is started. We override this method because the run () method inherited from Thread class is empty so we redefine the method in the subclass in order to make the thread do something useful.
Once the subclass is defined, you just need to create an object of this class and invoke its start () method in the client program (i.e. in main () method) to start the thread. The start () method registers the thread with the thread scheduler. The scheduler might be part of the JVM or the host OS. The scheduler determines which thread is running on the CPU at any given time. Note that when you call the start () method for a Thread object it does not mean that it will execute immediately rather the scheduler places the thread in the queue for execution where it competes for CPU time with all other threads. Eventually the thread will execute when the other running thread release the CPU and at that time its run () method will be called. The new thread continues to run until the run () method exits, at which point it ceases to exist. Do not call the run () method directly. If you do so, it does not create a new thread, instead the run () method is simply executed in the caller’s thread, just like any other method call.
Now let us consider a program that creates and executes a thread
class MyThread extends Thread { private int threadNum; MyThread(int n) { threadNum = n; } public void run() { System.out.println("Thread Number " + threadNum + " is Running"); } } public class CreatingThread { public static void main(String[] args) { System.out.println("Main thread Start"); MyThread t1 = new MyThread(1); MyThread t2 = new MyThread(2); MyThread t3 = new MyThread(3); t1.start(); // starts thread t1 t2.start(); // starts thread t2 t3.start(); // starts thread t3 System.out.println ("Main thread Finished"); } }
Explanation: In this program, we create and run a thread. We begin by creating a class Mythread which is a subclass of Thread class. The MyThreadclass contains an instance variable threadNum. Which stores the thread number and a single parameterized constructor to initialize threadNum field. Here, we also override the run () method of the Thread class. This method contains the code executed when a new thread started.
In main () method, the statement,
MyThread t1 = new MyThread(1);
creates an object of MyThreadclass and invokes its single parameterized constructor and assigns the value 1 to a threadNum field. Then its reference is assigned to the variable t1. Similarly, two more threads create whose references stored in t2 and t3.
Once the thread creates, it does not starts executing by itself, so you need to start it, for this, we call the start () method which inherits from Thread class for each object. For example The statement,
t1.start();
starts the start() method for the t1 object. At this point, the thread is ready to run and waits for its chance to be selected by the scheduler for execution. When it gets selected by the scheduler, the object’s run() method starts where it executes the statement (s) in its body and returns to the calling method.
Similarly, the start () method associated with other threads starts the execution of other threads. Finally, all three threads are executing in parallel with the main thread. From the output, you can see that the threads t1, t2, and t3 continue to run even if all the statements of the main() method executed.
The following points should remember when creating and running threads.
• You can invoke start() method only once for each thread. If you try to invoke the start() method again, an IllegalThreadStateException exception raised.
• Each thread must have a name. If you do not specify the name, the Java runtime system gives it one, usually the numbering scheme like thread-1, thread- 2 and so on.
• Every thread in Java has its call stack.
• You cannot control the JVM thread scheduler. The thread scheduler decides who run and for how long and where the threads go when the scheduler decides to kick them out of the current running state.
• The statement of each thread’s run() method interleaved in a non-deterministic fashion, so in general, it is not possible to predict possibly the order in which things happen in different threads.
• It is essential to declare the run() method to be public otherwise the compiler generate the error “Attempting to assign weaker access privileges; was public.”
Now let us consider a program that demonstrates the use of constructors and methods of the thread class.
class MyThread extends Thread {
privateint delay;
Mythread (String str,int d){
super(str);//calls Thread class constructor Thread(String name)
delay = d;// time for which thread sleeps
}
publicvoid run(){
for(int i =0; i<5; i++){
System.out.println( getName()+” thread is running”);
try{// put thread to sleep for delay amount of time
sleep(delay);// put thread to sleep
}
//if thread interrupted while sleeping, print stack trace
catch(interruptdException e){
e.printStacktrace();
}
}
system.out.println(getName()+” thread is finished”);
}
}
publicclass ThreadManipulation {
publicstaticvoid main(String[] args){
system.out.println(“Main thread starts”);
MyThread t1 =new MyThread(“First”,500);
MyThread t2 =new MyThread(“Second”,300);
MyThread t3 =new MyThread(“Third”,600);
t1.start();
t2.start();
t3.start();
System.out.println(“Main thread is finished”);
}
}
Explanation: The above program shows how the constructors and methods of the Thread class used. Here, we have created a subclass MyThread that extends Thread class. This class consists of a field which stores the time in milliseconds for which the thread sleep. It also contains a parameterized constructor that contains two parameters str of String type and d of int type. This constructor calls the superclass constructor that sets the Thread’s name to the value passed in str and delay field is set to value passed in d.
The run () method of MyThread class is defined to override the empty method implementation in the Thread class. This method contains a for loop that iterates five times. In each iteration, the method displays the name of the thread that is running using the getName () method of the Thread class. Then the static method sleep () of the Thread class is called that suspends the execution of the thread for the specified time that stored in delay field. It is done to introduce a delay and give other previously started threads a chance to execute. Note that we have put the sleep () method in the try block because the sleep () method might throw an InterruptedException checked exception when a sleeping thread’s interrupt method called.
When the thread awakens after the specified period, it again gets ready to run and waits for its chance to get selected for execution. After the loop has finished, the appropriate message is displayed, and it exits the run () method.
The class ThreadManipulation contains the main () method that creates three threads t1,t2 and t3 in addition to the initial thread (i.e., main thread) that the interpreter creates to invoke the main () method. The threads t1, t2, and t3 are assigned names First, Second and Third respectively along with the value for the time delay, i.e., 500, 300 and 600 respectively by calling their
appropriate constructors. Then we call the start ()method for these threads t1,t2, and t3 to start the thread of execution beginning at the run () method.
Eventually, all the threads, i.e., main, t1,t2, and t3 are running concurrently which is clear from the output where the output from each thread intermingled with each other. When the loop completes, the thread stops running and dies.
In a multi-threaded program, the main thread must be the last thread to finish running, but from the above program’s output, we see that the main thread finished before the other threads. One way to ensure that the main thread finishes last is to introduce a long enough delay by calling the sleep() method within the main() method as follows:
publicstatic void main(String[] args) {
.............
t3.start();
for(int i =0; i>5; i++){
System.out.println(Thread.CurrentThread().getName()+“is running”);
try{
thread.sleep(1000);
}
catch(InterruptException e){
e.printStackTrace();
}
}
.............
}
Creating Thread Using Runnable Interface
Another way to create a thread in Java is to define a class that implements the Runnable interface. The previous technique of creating threads by extending the Thread class does not work when you want a class that extends another class and can also run as a thread. It is because java supports only single inheritance, i.e., does not allow a class to extend more than one class. So in such a case implement the Runnable interface. The Runnable interface declares only one method run () that contains the code executed when the thread started. Therefore, if you define a class that implements the Runnable interface, then it must implement the run () method.
The Runnable interface commonly used when you add multithreading support to applets for animation or other purposes. It is required because the Applet class already extends java.applet.Applet class and it not possible to extend the Thread class.
Now let us consider a class MyThread that implements the Runnable interface.
class MyThread implements Runnable {
privateint threadId;
privateint delay;
MyThread(int id,int d){
threadId=id;
delay = d;//time for which thread sleeps
}
publicvoid run(){
for(int i=0;i<5;i++){
System.out.println(“Thread “+ threadId +” is running”);
try{
Thread.sleep(delay);
}
catch(InterruptedException e){
e.printStackTrace();
}
}
System.out.println(“Thread “+ threadId +” is Finished”);
}
}
The MyThread class consists of two fields threadId and delay both of type into The threadId field is used to assign a thread number to a thread and delay field is used to give time for which the thread sleeps. It also contains a parameterized constructor that contains two parameters id and d both of type into this constructor sets the value for the threadId and delay field.
The run () method of the Runnable interface implemented. This method contains the code executed when the calling thread starts execution. This method contains the code similar to the one discussed earlier in the previous example.
After creating the MyThread class, create a Runnable instance of the defines class. The statement
MyThread r1 = new MyThread(1,500);
OR Runnable r1 = new MyThread(1,500);
creates a Runnable instance of the Mythread class and assigns an appropriate value to its fields using MyThreadclass constructor.
Now create an object of the Thread class by passing your class’s instance (i.e., r1) to the
Thread (Runnable target) constructor. This object is your Thread object. The following statement performs the task.
Thread t1 = new Thread(r1);
You can also combine the creation of Runnable instance as well as an object of the Thread class in a single statement as follows,
Thread t1 = new Thread(new MyThread(1,500));
The purpose of invoking the Thread (Runnable target) constructor is to connect the Runnable object to the Thread API that allows the API to identify the location of the run () method when a thread starts.
As you know that the new thread does not begin execution until its start () method is invoked, so invoke the start () method on your Thread object using the following statement
t1.start () ;
The complete program is as follows,
class MyThread implements Runnable {
private int threadId;
private int delay;
MyThread(int id,int d) {
threadId=id;
delay = d;//time for which thread sleeps
}
public void run() {
for(int i=0;i<5;i++) {
System.out.println(“Thread “ + threadId +” is running”);
try {
Thread.sleep(delay);
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(“Thread “ + threadId +” is Finished”);
}
}
public class RunnableThread {
public static void main(String[] args) {
System.out.println(“Main thread starts”);
MyThread r1 = new MyThread(1,500);
MyThread r2 = new MyThread(2,300);
MyThread r3 = new MyThread(3,600);
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
Thread t3 = new Thread(r3);
t1.start();
t2.start();
t3.start();
System.out.println(“Main thread is finished”);
}
}
From the above discussion, we conclude that defining, instantiating and starting a new thread using a Runnable interface involves the following steps.
1. Define the class that implements the Runnable interface and implement the run () method of the Runnable interface in the class.
2. Create an instance of the defined class.
3. Create an instance of the Thread class using the Thread (Runnable target) constructor.
4. Start the thread by invoking the start () method on your Thread object.