Learn about thread creation and daemon threads in Java programming

  • 2020-04-01 04:26:01
  • OfStack

Two ways of creating threads and their advantages and disadvantages are compared
1, through the implementation of Runnable interface thread creation
(1). Define a class to implement the Runnable interface and override the run() method in the interface. Add specific task code or processing logic to the run() method.
(2). Create the object of the Runnable interface implementation class.
(3). To create an object of the Thread class, we need to encapsulate the object of the previous Runnable interface implementation class. (interfaces can implement multiple inheritance)
(4). Call the start() method of the Thread object to start the Thread
Sample code:


package demo.thread; 
 
public class TreadDemo1 implements Runnable { 
  private int countDown = 10; 
  @Override 
  //Define the task in the run method
  public void run() { 
    while (countDown-- > 0) { 
      System.out.println("#" + Thread.currentThread().getName() + "(" 
          + countDown + ")"); 
    } 
  } 
 
  public static void main(String[] args) { 
    //The run method in Runnable is an empty method that does not generate any thread behavior and must explicitly attach a task to the thread
    TreadDemo1 tt=new TreadDemo1(); 
    new Thread(tt).start(); 
    new Thread(tt).start(); 
    System.out.println(" Countdown before launch: "); 
  } 
} 

  Operation results:
Countdown before launch:


#Thread-1(8)
#Thread-1(7)
#Thread-1(6)
#Thread-1(5)
#Thread-1(4)
#Thread-1(3)
#Thread-1(2)
#Thread-1(1)
#Thread-1(0)
#Thread-0(9)

2. Create threads by inheriting the Thread class
(1). First, define a class to inherit the Thread parent class and override the run() method in the parent class. Add specific task code or processing logic to the run() method.
(2). Directly create an object of class ThreadDemo2, or declare the variable as the type of the parent class by utilizing polymorphism.
(3). Call the start method, thread t starts, and implicitly call the run() method.
Sample code:


package demo.thread; 
 
public class ThreadDemo2 extends Thread { 
  private int countDown = 10; 
 
  @Override 
  //Define the task in the run method
  public void run() { 
    while (countDown-- > 0) { 
      System.out.println("#" + this.getName() + "(" + countDown + ")"); 
    } 
  } 
 
  public static void main(String[] args) { 
    new ThreadDemo2().start(); 
    new ThreadDemo2().start(); 
    //Because the start method returns quickly, the main thread can perform other operations, with two separate threads running concurrently
    System.out.println(" Countdown before launch: "); 
  } 
} 

  Operation results:


#Thread-0(9)
#Thread-0(8)
#Thread-0(7)
#Thread-0(6)
#Thread-0(5)
#Thread-0(4)
#Thread-0(3)
#Thread-0(2)
#Thread-0(1)
#Thread-0(0)

Countdown before launch:


#Thread-1(9)
#Thread-1(8)
#Thread-1(7)
#Thread-1(6)
#Thread-1(5)
#Thread-1(4)
#Thread-1(3)
#Thread-1(2)
#Thread-1(1)
#Thread-1(0)

3. Comparison of the two methods
First, analyze the output results of the two methods, the same is the creation of two threads, why the results are different?
Threads created using the implementation Runnable interface method can share the same target object (TreadDemo1 tt=new TreadDemo1();) , which implements multiple identical threads to process the same resource.
Then look at an explanation from the JDK:
The Runnable interface should be implemented by classes that intend to execute the example through a thread. The class must define a parameterless method called run.
This interface is designed to provide a common protocol for objects that want to execute code at activity time. For example, the Thread class implements Runnable. Activation means that a thread has started and has not stopped.
In addition, Runnable provides a means of activation for classes that are not subclasses of threads. By instantiating a Thread instance and targeting itself, you can run a class that implements Runnable without creating a subclass of the Thread. In most cases, the Runnable interface should be used if you want to override only the run() method and not the other Thread methods. This is important because a class should not be subclassed unless the programmer intends to modify or enhance its basic behavior.
 
By inheriting the Thread class:
(1) advantages: easy to write, if you need to access the currentThread, do not use thread.currentthread () method, directly use this, you can get the currentThread.
(2) disadvantage: because the Thread class already inherits the Thread class, it cannot inherit from any other parent class.
Implementation of Runnable interface:
(1) advantages: the thread class only implements the Runable interface and can inherit from other classes. In this way, multiple threads can share the same target object, so it is very suitable for multiple threads to handle the same resource, so that the CPU code and data can be separated to form a clear model, which better reflects the object-oriented idea.
(2) disadvantages: programming is a bit more complicated, and if you need to access the currentThread, you must use the thread.currentthread () method.

Background thread (daemon thread)
The so-called background thread refers to the thread that provides a common service in the background when the program is running, and this thread is not an indispensable part of the program. So when all the non-background threads end, the program terminates, killing all the background threads. Conversely, the program does not terminate as long as any non-background threads (user threads) are running. A background thread terminates its run method without executing the finally clause. The child threads created by the background thread are also background threads. Here is an example of a background thread:


package demo.thread; 
 
import java.util.concurrent.TimeUnit; 
 
public class DaemonDemo implements Runnable { 
  @Override 
  public void run() { 
    try { 
      while (true) { 
        Thread.sleep(1000); 
        System.out.println("#" + Thread.currentThread().getName()); 
      } 
    } catch (InterruptedException e) { 
      e.printStackTrace(); 
    } finally {//The background thread does not execute the finally clause
      System.out.println("finally "); 
    } 
  } 
 
  public static void main(String[] args) { 
    for (int i = 0; i < 10; i++) { 
      Thread daemon = new Thread(new DaemonDemo()); 
      //Must be set as a background thread before start
      daemon.setDaemon(true); 
      daemon.start(); 
    } 
    System.out.println("All daemons started"); 
    try { 
      TimeUnit.MILLISECONDS.sleep(1000); 
    } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
    } 
  } 
} 

 
Operation results:


All daemons started
#Thread-2
#Thread-3
#Thread-1
#Thread-0
#Thread-9
#Thread-6
#Thread-8
#Thread-5
#Thread-7
#Thread-4

Analysis: as you can see from the results, the ten child threads do not print out the wireless loop, but the JVM forces all background threads to shut down after the main thread (main()) exits. There will be no desired form of validation, such as the finally clause not being executed.


Related articles: