How Java implements multithreading

Keywords: Java JDK

Java There are three main ways to realize multithreading: inheriting Thread class, implementing Runnable interface, using Executor Service, Callable and Future to realize multithreading with returned results. The first two methods of thread execution have no return value, only the last one is with return value.


1. Implementing multithreading by inheriting Thread class
Although the method of inheriting the Thread class is listed as a multi-threaded implementation by me, Thread is essentially an instance of implementing the Runnable interface, which represents an instance of a thread, and the only way to start a thread is through the start() instance method of the Thread class. The start() method is a native method that starts a new thread and executes the run() method. This way to achieve multithreading is very simple. By extending Thread directly through its own class and copying run() method, you can start a new thread and execute the run() method you defined. For example:

  1. public class MyThread extends Thread {  
  2.   public void run() {  
  3.    System.out.println("MyThread.run()");  
  4.   }  
  5. }  
Start threads where appropriate as follows:
  1. MyThread myThread1 = new MyThread();  
  2. MyThread myThread2 = new MyThread();  
  3. myThread1.start();  
  4. myThread2.start();  

2. Implementation of Runnable Interface for Multithreading
If your own class already extends another class, you cannot extend Thread directly. At this point, you must implement a Runnable interface, as follows:
  1. public class MyThread extends OtherClass implements Runnable {  
  2.   public void run() {  
  3.    System.out.println("MyThread.run()");  
  4.   }  
  5. }  
To start MyThread, you need to first instantiate a Thread and pass in your own MyThread instance:
  1. MyThread myThread = new MyThread();  
  2. Thread thread = new Thread(myThread);  
  3. thread.start();  
In fact, when a Runnable target parameter is passed to Thread, the run() method of Thread calls target.run(), referring to the JDK source code:
  1. public void run() {  
  2.   if (target != null) {  
  3.    target.run();  
  4.   }  
  5. }  

3. Using ExecutorService, Callable and Future to Realize Multithreading with Return Results
Executor Service, Callable, Future are all functional classes in the Executor framework. For a detailed understanding of the Executor framework, you can visit http://www.javaeye.com/topic/366591, which is explained in detail here. Threads returning results are a new feature introduced in JDK 1.5. It's really practical. With this feature, I don't have to go through a lot of trouble to get the return value, and even if it's implemented, there may be a lot of loopholes.
Tasks with returnable values must implement the Callable interface. Similarly, tasks without returnable values must have the Runnable interface. After the Callable task is executed, a Future object can be obtained, and the Object returned by the Callable task can be obtained by calling get on the object. Combined with the thread pool interface ExecutorService, the legendary multithreading with the return result can be realized. The following provides a complete multi-threaded test example with returned results, which has been verified under JDK 1.5 that no problem can be used directly. The code is as follows:

  1. import java.util.concurrent.*;  
  2. import java.util.Date;  
  3. import java.util.List;  
  4. import java.util.ArrayList;  
  5.   
  6. /** 
  7. * Threads with return values 
  8. */  
  9. @SuppressWarnings("unchecked")  
  10. public class Test {  
  11. public static void main(String[] args) throws ExecutionException,  
  12.     InterruptedException {  
  13.    System.out.println("----The program starts to run----");  
  14.    Date date1 = new Date();  
  15.   
  16.    int taskSize = 5;  
  17.    //Create a thread pool  
  18.    ExecutorService pool = Executors.newFixedThreadPool(taskSize);  
  19.    //Create multiple tasks with return values  
  20.    List<Future> list = new ArrayList<Future>();  
  21.    for (int i = 0; i < taskSize; i++) {  
  22.     Callable c = new MyCallable(i + " ");  
  23.     //Executing tasks and obtaining Future objects  
  24.     Future f = pool.submit(c);  
  25.     // System.out.println(">>>" + f.get().toString());  
  26.     list.add(f);  
  27.    }  
  28.    //Close thread pool  
  29.    pool.shutdown();  
  30.   
  31.    //Get the results of all concurrent tasks  
  32.    for (Future f : list) {  
  33.     //Get the return value of the task from the Future object and output it to the console  
  34.     System.out.println(">>>" + f.get().toString());  
  35.    }  
  36.   
  37.    Date date2 = new Date();  
  38.    System.out.println("----Program End Running----,Program run time["  
  39.      + (date2.getTime() - date1.getTime()) + "Milliseconds)");  
  40. }  
  41. }  
  42.   
  43. class MyCallable implements Callable<Object> {  
  44. private String taskNum;  
  45.   
  46. MyCallable(String taskNum) {  
  47.    this.taskNum = taskNum;  
  48. }  
  49.   
  50. public Object call() throws Exception {  
  51.    System.out.println(">>>" + taskNum + "Task Start");  
  52.    Date dateTmp1 = new Date();  
  53.    Thread.sleep(1000);  
  54.    Date dateTmp2 = new Date();  
  55.    long time = dateTmp2.getTime() - dateTmp1.getTime();  
  56.    System.out.println(">>>" + taskNum + "Mission termination");  
  57.    return taskNum + "Task Returns Running Results,Current Task Time[" + time + "Milliseconds)";  
  58. }  
  59. }  
Code description:
The Executors class in the above code provides a series of factory methods for pioneering thread pools, and the returned thread pools all implement the ExecutorService interface.
public static ExecutorService newFixedThreadPool(int nThreads) 
Create a pool of threads with a fixed number of threads.
public static ExecutorService newCachedThreadPool() 
Create a cacheable thread pool and call execute to reuse previously constructed threads if they are available. If no existing thread is available, create a new thread and add it to the pool. Terminate and remove threads that have not been used for 60 seconds from the cache.
public static ExecutorService newSingleThreadExecutor() 
Create a single threaded Executor.
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) 
Create a thread pool that supports timed and periodic task execution, which in most cases can be used to replace the Timer class.

ExecutoreService provides a submit() method that passes a Callable, or Runnable, back to Future. If the Executor background thread pool has not completed the Callable calculation, the call returns the get() method of the Future object, blocking until the calculation is completed.

Reproduced in: http://www.cnblogs.com/yezhenhan/archive/2012/01/09/2317636.html

Posted by zTagged on Sun, 16 Jun 2019 12:57:00 -0700