Getting started with Java - advanced tutorial - 07. Multithreading

Original address: http://www.work100.net/training/java-multi-threading.html
More tutorials: Beam cloud - free course

Multithreading

Serial number Chapter in text video
1 Summary -
2 The life cycle of a thread -
3 thread priority -
4 Create a thread -
5 Creating threads by implementing the Runnable interface -
6 Create threads by inheriting threads -
7 Create threads by inheriting threads -
8 Creating threads through Callable and Future -
9 Comparison of three ways to create threads -
10 Several main concepts of thread -
11 Use of multithreading -

Please refer to the navigation above for reading

1. overview

Java provides built-in support for multithreaded programming. A thread refers to a single sequential control flow in a process. Multiple threads can be concurrent in a process, and each thread executes different tasks in parallel.

Multithreading is a special form of multitasking, but it uses less resource overhead.

Another term related to threads is defined here - process: a process includes memory space allocated by the operating system, including one or more threads. A thread cannot exist independently. It must be part of a process. A process runs until all non - daemons have finished running.

Multithreading can satisfy programmers to write efficient programs to make full use of CPU.

2. The life cycle of a thread

Thread is a process of dynamic execution, and it also has a process from generation to death.

The following figure shows the complete life cycle of a thread.

  • New status:

    When a Thread object is created with the new keyword and the Thread class or its subclass, the Thread object is in the new state. It remains in this state until the Thread of program start().

  • Ready status:

    When the thread object calls the start() method, the thread enters a ready state. The ready thread is in the ready queue, waiting for the scheduling of the thread scheduler in the JVM.

  • Operation status:

    If the ready thread gets CPU resources, it can run(), and the thread is running. Threads in the running state are the most complex, and can become blocked, ready, and dead.

  • Blocking status:

    If a thread executes sleep, suspend and other methods and loses the occupied resources, the thread will enter the blocking state from the running state. You can re-enter the ready state after the sleep time has expired or the device resources have been obtained. There are three types:

    • Waiting for blocking: the thread in the running state executes the wait() method, which makes the thread enter the waiting blocking state.
    • Synchronization block: the thread failed to acquire the synchronized synchronization lock (because the synchronization lock is occupied by other threads).
    • Other blocking: when an I/O request is made by calling the thread's sleep() or join(), the thread will enter the blocking state. When the sleep() state times out, the join() waits for the thread to terminate or time out, or the I/O processing is completed, and the thread turns back to the ready state.
  • State of death:

    When a running thread completes a task or other termination conditions occur, the thread switches to the termination state.

3. Priority of thread

Each Java thread has a priority, which helps the operating system determine the scheduling order of the threads.

The priority of a Java thread is an integer with a value range of 1 (thread. Min? Priority) - 10 (thread. Max? Priority).

By default, each thread is assigned a priority of NORM_PRIORITY (5).

Threads with higher priority are more important to the program, and processor resources should be allocated before threads with lower priority. However, thread priority does not guarantee the order of thread execution, and it is very platform dependent.

4. Create a thread

Java provides three ways to create threads:

Through the implementation of Runnable interface;
By inheriting the Thread class itself;
Create threads through Callable and Future.

5. Create a thread by implementing the Runnable interface

The easiest way to create a thread is to create a class that implements the Runnable interface.

In order to implement Runnable, a class only needs to execute a method call run(), which is declared as follows:

public void run()

You can override this method. It's important to understand that run() can call other methods, use other classes, and declare variables just like the main thread.

After creating a class that implements the Runnable interface, you can instantiate a thread object in the class.

Thread defines several construction methods, which we often use:

Thread(Runnable threadOb,String threadName);

Here, threadOb is an instance of a class that implements the Runnable interface, and threadName specifies the name of the new thread.

After the new thread is created, you call its start() method and it will run.

void start();

Here is an example of creating a thread and starting it to execute:

class RunnableDemo implements Runnable {
   private Thread t;
   private String threadName;

   RunnableDemo( String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }

   public void run() {
      System.out.println("Running " +  threadName );
      try {
         for(int i = 4; i > 0; i--) {
            System.out.println("Thread: " + threadName + ", " + i);
            // Let the thread sleep for a while
            Thread.sleep(50);
         }
      }catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }

   public void start () {
      System.out.println("Starting " +  threadName );
      if (t == null) {
         t = new Thread (this, threadName);
         t.start ();
      }
   }
}

public class TestThread {

   public static void main(String[] args) {
      RunnableDemo R1 = new RunnableDemo( "Thread-1");
      R1.start();

      RunnableDemo R2 = new RunnableDemo( "Thread-2");
      R2.start();
   }   
}

The results of compiling the above programs are as follows:

Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.

6. Create Thread by inheriting Thread

The second way to create a Thread is to create a new class that inherits the Thread class and then creates an instance of the class.

The inheritance class must override the run() method, which is the entry point for the new thread. It must also call the start() method to execute.

Although this method is listed as a multi-threaded implementation, it is also an instance of implementing the Runnable interface in essence.

class ThreadDemo extends Thread {
   private Thread t;
   private String threadName;

   ThreadDemo( String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }

   public void run() {
      System.out.println("Running " +  threadName );
      try {
         for(int i = 4; i > 0; i--) {
            System.out.println("Thread: " + threadName + ", " + i);
            // Let the thread sleep for a while
            Thread.sleep(50);
         }
      }catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }

   public void start () {
      System.out.println("Starting " +  threadName );
      if (t == null) {
         t = new Thread (this, threadName);
         t.start ();
      }
   }
}

public class TestThread {

   public static void main(String[] args) {
      ThreadDemo T1 = new ThreadDemo( "Thread-1");
      T1.start();

      ThreadDemo T2 = new ThreadDemo( "Thread-2");
      T2.start();
   }   
}

The results of compiling the above programs are as follows:

Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.

7.Thread method

The following table lists some important methods of the Thread class:

Serial number Method description
1 Public void start() < br > causes the thread to start executing; the Java virtual machine calls the run method of the thread.
2 Public void run() < br > if the thread is constructed with an independent Runnable run object, the run method of the Runnable object is called; otherwise, the method does not perform any operation and returns.
3 Public final void setname (string name) < br > change the thread name to be the same as the parameter name.
4 Public final void setpriority (int priority) < br > change the priority of the thread.
5 Public final void setdaemon (Boolean on) < br > marks the thread as a guardian or user thread.
6 Public final void join (long millisec) < br > the maximum waiting time for the thread to terminate is millisecond.
7 Public void interrupt() < br > interrupts a thread.
8 Public final Boolean isalive() < br > tests whether the thread is active.

Test whether the Thread is active. The above method is called by the Thread object. The following method is a static method of the Thread class.

Serial number Method description
1 Public static void yield() < br > pauses the currently executing thread object and executes other threads.
2 Public static void sleep (long millisec) < br > causes the currently executing thread to sleep (pause execution) within the specified number of milliseconds, which is affected by the accuracy and accuracy of the system timer and scheduler.
3 Public static Boolean holdlock (object x) < br > returns true when and only when the current thread holds the monitor lock on the specified object.
4 Public static thread currentthread() < br > returns a reference to the currently executing thread object.
5 Public static void dumpstack() < br > prints the stack trace of the current thread to the standard error stream.

Example

The following ThreadClassDemo program demonstrates some methods of Thread class:

DisplayMessage.java file code:

// Filename: DisplayMessage.java
// Creating threads by implementing the Runnable interface
public class DisplayMessage implements Runnable {
   private String message;

   public DisplayMessage(String message) {
      this.message = message;
   }

   public void run() {
      while(true) {
         System.out.println(message);
      }
   }
}

Guissanumber.java file code:

// Filename: GuessANumber.java
// Create a Thread by inheriting the Thread class

public class GuessANumber extends Thread {
   private int number;
   public GuessANumber(int number) {
      this.number = number;
   }

   public void run() {
      int counter = 0;
      int guess = 0;
      do {
         guess = (int) (Math.random() * 100 + 1);
         System.out.println(this.getName() + " guesses " + guess);
         counter++;
      } while(guess != number);
      System.out.println("** Correct!" + this.getName() + "in" + counter + "guesses.**");
   }
}

ThreadClassDemo.java file code:

// Filename: ThreadClassDemo.java
public class ThreadClassDemo {

   public static void main(String [] args) {
      Runnable hello = new DisplayMessage("Hello");
      Thread thread1 = new Thread(hello);
      thread1.setDaemon(true);
      thread1.setName("hello");
      System.out.println("Starting hello thread...");
      thread1.start();

      Runnable bye = new DisplayMessage("Goodbye");
      Thread thread2 = new Thread(bye);
      thread2.setPriority(Thread.MIN_PRIORITY);
      thread2.setDaemon(true);
      System.out.println("Starting goodbye thread...");
      thread2.start();

      System.out.println("Starting thread3...");
      Thread thread3 = new GuessANumber(27);
      thread3.start();
      try {
         thread3.join();
      }catch(InterruptedException e) {
         System.out.println("Thread interrupted.");
      }
      System.out.println("Starting thread4...");
      Thread thread4 = new GuessANumber(75);

      thread4.start();
      System.out.println("main() is ending...");
   }
}

The running results are as follows. The results of each run are different.

Starting hello thread...
Starting goodbye thread...
Hello
Hello
Hello
Hello
Hello
Hello
Goodbye
Goodbye
Goodbye
Goodbye
Goodbye
.......

8. Create threads through Callable and Future

  • Create the implementation class of the Callable interface and implement the call() method, which will be the thread execution body with return value.
  • 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.
  • Use the FutureTask object as the target of the Thread object to create and start a new Thread.
  • Call the get() method of the FutureTask object to get the return value after the execution of the child thread.

Example

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 = 0;i < 100;i++)  
        {  
            System.out.println(Thread.currentThread().getName()+" Loop variable of i Value"+i);  
            if(i==20)  
            {  
                new Thread(ft,"Thread with return value").start();  
            }  
        }  
        try  
        {  
            System.out.println("Return value of child thread:"+ft.get());  
        } catch (InterruptedException e)  
        {  
            e.printStackTrace();  
        } catch (ExecutionException e)  
        {  
            e.printStackTrace();  
        }  

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

9. Comparison of three ways to create threads

  • When multithreading is created by implementing Runnable and Callable interfaces, the thread class only implements Runnable or Callable interfaces, and can inherit other classes.
  • When using the method of inheriting Thread class to create multithread, it is easy to write. If you need to access the current Thread, you don't need to use the Thread.currentThread() method. You can get the current Thread by using this directly.

10. Several main concepts of thread

When multithreading, you need to understand the following concepts:

  • Thread synchronization
  • Inter thread communication
  • thread deadlock
  • Thread control: suspend, stop, and resume

11. Use of multithreading

The key to the effective use of multithreading is to understand that programs are executed concurrently rather than serially. For example, there are two subsystems in the program that need to be executed concurrently. At this time, multi-threaded programming is needed.

Through the use of multithreading, you can write very efficient programs. However, please note that if you create too many threads, the efficiency of program execution is actually reduced rather than improved.

Remember that context switching overhead is also important. If you create too many threads, the CPU will spend more time in context switching than executing the program!

Last article: Mail sending and receiving
Next article: Applet

If you are interested in the content of the course, you can scan the code to pay attention to our official account or QQ group, and pay attention to our curriculum updates in time.


Tags: Java Programming less jvm

Posted on Sat, 07 Mar 2020 19:18:15 -0500 by Onloac