Three ways to create threads in Java and their comparisons

1. There are three main ways to create threads in Java:

1. Inherit the Thread class to create a thread class

  • Define a subclass of the Thread class and override the run method of the class. The method body of the run method represents the task to be completed by the thread. Therefore, the run() method is called the executor.
  • Creating an instance of the Thread subclass creates a thread object.
  • Call the thread object's start() method to start the thread.

Example code is:

package com.thread;  

public class FirstThreadTest extends Thread{  
int i = ;  
//Rewrite the run method, the method body of the run method is the on-site execution body  
public void run()  
{  
    for(;i<100;i++){  
    System.out.println(getName()+"  "+i);  
    }  
}  
public static void main(String[] args)  
{  
    for(int i = ;i< 100;i++)  
    {  
        System.out.println(Thread.currentThread().getName()+"  : "+i);  
        if(i==20)  
        {  
            new FirstThreadTest().start();  
            new FirstThreadTest().start();  
        }  
    }  
}  
}

The Thread.currentThread() method in the above code returns the currently executing thread object. The GetName() method returns the name of the thread that called the method.

2. Create a thread class through the Runnable interface

  • Define the implementation class of the runnable interface, and override the run() method of the interface. The method body of the run() method is also the thread execution body of the thread.
  • Create an instance of the Runnable implementation class, and use this instance as the target of Thread to create a Thread object, which is the real thread object.
  • Call the thread object's start() method to start the thread.

Example code is:

package com.thread;  

public class RunnableThreadTest implements Runnable  
{  

private int i;  
public void run()  
{  
    for(i = ;i <100;i++)  
    {  
        System.out.println(Thread.currentThread().getName()+" "+i);  
    }  
}  
public static void main(String[] args)  
{  
    for(int i = ;i < 100;i++)  
    {  
        System.out.println(Thread.currentThread().getName()+" "+i);  
        if(i==20)  
        {  
            RunnableThreadTest rtt = new RunnableThreadTest();  
            new Thread(rtt,"new thread 1").start();  
            new Thread(rtt,"new thread 2").start();  
        }  
    }  
}   
}

The execution process of the thread is very simple. When the code start() is executed, the void run(); method rewritten in the object will be executed. After the method is executed, the thread will die.

3. Create threads through Callable and Future
(1) Create an implementation class of the Callable interface and implement the call() method. The call() method will serve as the thread execution body and have a return value.

public interface Callable
{
V call() throws Exception;
}

(2) Create an instance of the Callable implementation class, and use the FutureTask class to wrap the Callable object, which encapsulates the return value of the call() method of the Callable object. (FutureTask is a wrapper that is created by accepting a Callable, which implements both the Future and Runnable interfaces.)

(3) Use the FutureTask object as the target of the Thread object to create and start a new thread.

(4) Call the get() method of the FutureTask object to obtain the return value after the execution of the child thread ends

Example code:

package com.thread;  

import java.util.concurrent.Callable;  
import java.util.concurrent.ExecutionException;  
import java.util.concurrent.FutureTask;  

public class CallableThreadTest implements Callable<Integer>  
{  

public static void main(String[] args)  
{  
    CallableThreadTest ctt = new CallableThreadTest();  
    FutureTask<Integer> ft = new FutureTask<>(ctt);  
    for(int i = ;i < 100;i++)  
    {  
        System.out.println(Thread.currentThread().getName()+" the loop variable i the value of"+i);  
        if(i==20)  
        {  
            new Thread(ft,"thread with return value").start();  
        }  
    }  
    try  
    {  
        System.out.println("The return value of the child thread:"+ft.get());  
    } catch (InterruptedException e)  
    {  
        e.printStackTrace();  
    } catch (ExecutionException e)  
    {  
        e.printStackTrace();  
    }  

    }  

@Override  
public Integer call() throws Exception  
{  
    int i = ;  
    for(;i<100;i++)  
    {  
        System.out.println(Thread.currentThread().getName()+" "+i);  
    }  
    return i;  
}  

}

2. Comparison of three ways to create threads

1. When creating multi-threads by implementing Runnable and Callable interfaces,
The advantages are:
The thread class just implements the Runnable interface or the Callable interface, and can also inherit from other classes. In this way, multiple threads can share the same target object, so it is very suitable for multiple same threads to process the same resource, so that the CPU, code and data can be separated to form a clear model, which can better reflect object-oriented thinking.

The disadvantages are:
The programming is slightly more complicated, if you want to access the current thread, you have to use the Thread.currentThread() method.

2. When creating multi-threads by inheriting the Thread class,
The advantages are:
The writing is simple. If you need to access the current thread, you don't need to use the Thread.currentThread() method, you can directly use this to get the current thread.

The disadvantages are:
The thread class already inherits the Thread class, so it cannot inherit other parent classes.

3. The difference between Runnable and Callable
(1) The method specified (overridden) by Callable is call(), and the method specified (overridden) by Runnable is run().

(2) Callable tasks can return values ​​after execution, while Runnable tasks cannot return values.

(3) The call method can throw exceptions, but the run method cannot.

(4) Running the Callable task can get a Future object, which represents the result of the asynchronous calculation. It provides methods to check whether a computation is complete, wait for the computation to complete, and retrieve the result of the computation. Through the Future object, you can learn about the execution of the task, cancel the execution of the task, and obtain the execution result.

PS: If you don’t understand anything during the reading process, or if you have any questions you want to consult, you can join my Java learning exchange Q group: 927296445, and you can answer it at any time! There are also some Java study manuals, interview questions, development tools, PDF documents and book tutorials that I have compiled during this time. If necessary, I can share them with you for free.

Tags: Java Programmer IT

Posted by yanisdon on Sun, 08 May 2022 06:18:42 +0300