Java language learning day 14 - multithreading

1 thread and concurrency

1.1 difference between thread and process

  • Process: an application running in memory. Each process has its own independent memory space. There can be multiple threads in a process
  • Thread: an execution task in a process. A process can run multiple threads, and multiple threads can share data
  • Multi process: running multiple applications at the same time
  • Multithreading: running multiple tasks simultaneously in the same process
  • Concurrency: simultaneous and alternating
  • Parallel: simultaneously at the same time

Note: a process has at least one thread. In order to improve execution efficiency, you can start multiple control units in a process, which is multithreading

1.2 main thread

When running a Java program, there are already two threads, one is the main thread - automatically started when running the main method to start the JVM, and the other is the background thread - garbage collection maintained

1.3 thread creation and startup

  • Method 1: inherit Thread class
  1. Custom inheritance Thread
  2. Override run method
  3. Create custom class object
  4. The start method is called by the custom class object
//Inherit Thread class to define a Thread class
public class MyThread extends Thread {
    //Assign tasks
    public void run() {
        //Thread body. This method will be called automatically when the thread starts. Here is the main part of our code
        for (int i = 0; i < 100; i++) {
            System.out.println("Listen to the music");
        }
    }
}
public class ThreadDemo {
    public static void main(String[] args) {
        //Listening to music: Custom threads
        //new a custom thread object
        MyThread mt = new MyThread();
        //Start the thread and hand over the current thread to the CPU for scheduling
        //When CPU resources are seized, execute the run method
        call Thread of start method, JVM Automatically called run method.
        mt.start();
        //Main thread: playing games
        for (int i = 0; i < 100; i++) {
            System.out.println("play a game");
        }
    }
}
  • Mode 2: implement Runnable interface
  1. The custom class implements the Runnable interface
  2. Override run method
  3. Create custom class object
  4. Take the object of the custom class as the Thread class constructor, and call the start method of the Thread object
public class MyRunnable implements Runnable {
    //Assign tasks
    public void run() {
        //Thread body. This method will be called automatically when the thread starts. Here is the main part of our code
        for (int i = 0; i < 100; i++) {
            System.out.println("Listen to the music" + i);
        }
    }
}
public class RunnableDemo {
    public static void main(String[] args) {
        //Thread for listening to music
        MyRunnable mr = new MyRunnable();
        //The constructor of Thread was called
        Thread t = new Thread(mr);
        //Open thread
        t.start();
        //Main thread: playing games
        for (int i = 0; i < 100; i++) {
            System.out.println("play a game");
        }
    }
}

The first is easy to use and start a Thread. Many functions are defined in the Thread class

The second method depends on Thread, because there is only run method in Runnable. Please see the construction method of Thread

1.3.1 thread body - run method

No matter which way the thread is created, the run method should be overridden, because this is the thread body method, which will be called automatically after the thread is started

Randomness of thread execution:

Once a thread is started, it is an independent thread, waiting for the CPU to allocate resources. It will not end because the external thread that started it ends

1.3.2 thread startup

To start a Thread, you must call the start method in the Thread class Thread The bottom layer will call the run method of the Thread Only the start method of the Thread object can start a new Thread. If you call the run method of the object directly, it will not start a new Thread, but a single Thread

Note: to start a new thread, you cannot use the run() method, but only the start method.

1.4 thread life cycle and state

The life cycle of a thread consists of five phases: new, ready, running, blocking and destroying

  • New: when the program uses new to create a thread;
  • Ready: when the thread object calls the start() method, the thread is in the stage of waiting for the CPU to allocate resources. Whoever grabs the CPU resources first starts execution;
  • Run: when the ready thread is scheduled and obtains CPU resources, it enters the running state. The run method defines the operation and function of the thread;
  • Blocking: in the running state, the thread in the running state may become blocked for some reasons. For example, after sleep() and wait(), the thread is in the blocking state. At this time, other mechanisms are needed to wake up the thread in the blocking state, such as calling notify or notifyAll() methods The awakened threads will not execute the run method immediately, and they will wait for the CPU to allocate resources to enter the running state again;
  • Destroy: if the thread is forced to terminate in advance or terminated due to exceptions after normal execution, the thread will be destroyed to release resources;

1.5 methods of operating threads

1.5.1 join method

  • Function of join method: synchronization, which can turn parallelism between threads into serial

1.5.2 sleep method

  • The sleep method is used to pause the executing thread for a period of time and enter the blocking state

1.5.3 thread priority

  • Each thread has a priority, which is only related to the number of times the thread gets execution opportunities It does not mean that those with high priority must execute first. Which thread executes first depends on the call of CPU
  • setPriority(int x) and getPriority() of Thread object are used to set and obtain priority

1.5.4 background thread

  • Background thread: used to provide services for other threads Also known as daemon thread Garbage collection of JVM is a typical background thread

  • Features: if all foreground threads end, the background thread ends by itself

    The Thread object setDaemon(true) is used to set the background Thread

    setDaemon(true) must be called before start(), otherwise throw the IllegalThreadStateException exception

2. Thread safety

Security: when multiple threads access the same resource concurrently, it will lead to thread security

2.1 inheritance and Implementation

Use inheritance

public class Student extends Thread {
    //The total number of apples. If static is not used, multiple threads cannot share the same resource
    private static int number = 50;

    //Call the parent class parameterless constructor
    public Student() {
        super();
    }
    //Call the parameterized constructor of the parent class
    public Student(String name) {
        super(name);
    }

    //Coverage method
    public void run() {
        for (int i = 0; i < 50; i++) {
            if (number > 0) {
                System.out.println(super.getName() + "Ate an apple" + number--);
            }
        }
    }
}
public class ExtendsDemo {
    public static void main(String[] args) {
        //Create three threads and eat apples
        Thread t1 = new Student("B");
        Thread t2 = new Student("A");
        Thread t3 = new Student("C");
        //Open thread
        t1.start();
        t2.start();
        t3.start();
    }
}

Use implementation

public class Apple implements Runnable {
    //Total number of apples
    private int number = 50;

    public void run() {
        for (int i = 0; i < 50; i++) {
            if (number > 0) {
                //Get the current thread object first
                Thread t = Thread.currentThread();
                System.out.println(t.getName() + "Ate an apple" + number--);
            }
        }
    }
}
public class ImplementsDemo {
    public static void main(String[] args) {
        Apple apple = new Apple();
        Thread t1 = new Thread(apple, "Small A");
        Thread t2 = new Thread(apple, "Small B");
        Thread t3 = new Thread(apple, "Small C");
        //Open thread
        t1.start();
        t2.start();
        t3.start();
    }
}

Inheritance method:

  • In Java, classes are inherited singly. If Thread is inherited, the class cannot have other direct parent classes

  • In terms of operation, the inheritance method is simpler, and it is also easier to obtain the thread name.

  • From the point of view that multiple threads share the same resource, the inheritance mode cannot allow multiple threads to share the same resource (you can share the same resource with static modifier)

Implementation method:

  • Classes in Java can implement multiple interfaces. At this time, the class can inherit other classes and implement other interfaces (more elegant in design)

  • In terms of operation, it is also complex to obtain the thread name, so we have to use thread Currentthread() to get the reference of the current thread.

  • From the analysis of multithreading sharing the same resource, the implementation method can share the same resource with multithreading

2.2 thread synchronization

When multiple threads access the same resource object concurrently, thread insecurity may occur

2.2.1 synchronization code block

Syntax block synchronization code:

synchronized(Synchronous lock){
    Code that needs to be synchronized
}

Synchronous lock, also known as synchronous listening object / synchronous lock / synchronous listener / mutex:

In order to ensure that each thread can perform atomic operations normally, Java introduces thread synchronization mechanism

Note: at most one thread is allowed to have a synchronization lock at any time. Whoever gets the lock will execute. Other threads can only wait outside the code block.

public class Apple implements Runnable {
    //Total number of apples
    private int number = 50;

    public void run() {
        for (int i = 0; i < 50; i++) {
            //Synchronous code block
            //Lock object: ensure that the same object is used as the lock object
            synchronized (this) {
                if (number > 0) {
                    //Get the current thread object first
                    Thread t = Thread.currentThread();
                    System.out.println(t.getName() + "Ate an apple" + number--);
                }
            }
        }
    }
}
public class SynchronizedDemo {
    public static void main(String[] args) {
        Apple apple = new Apple();
        Thread t1 = new Thread(apple, "Small A");
        Thread t2 = new Thread(apple, "Small B");
        Thread t3 = new Thread(apple, "Small C");
        //Open thread
        t1.start();
        t2.start();
        t3.start();
    }
}

At this time, the synchronization lock this represents an Apple object, and there is only one Apple object in the program, so it can be used as a synchronization lock

2.2.2 synchronization method

The method using synchronized modification is called synchronous method Ensure that when thread A executes the method, other threads can only wait outside the method

synchronized  public  void  doWork(){
    //content
}

Who is the synchronization lock at this time? In fact, the object calling the current synchronization method:

  • For non static methods, the synchronization lock is this

  • For static methods, the synchronization lock is the bytecode object of the class where the current method is located

public class Apple implements Runnable {
    //Total number of apples
    private int number = 50;

    public void run() {
        for (int i = 0; i < 50; i++) {
            eat();
        }
    }
    //The eat method is a non static method that uses this as the lock object
    public synchronized void eat(){
        if (number > 0) {
            //Get the current thread object first
            Thread t = Thread.currentThread();
            System.out.println(t.getName() + "Ate an apple" + number--);
        }
    }
}
public class ImplementsDemo {
    public static void main(String[] args) {
        Apple apple = new Apple();
        Thread t1 = new Thread(apple, "Small A");
        Thread t2 = new Thread(apple, "Small B");
        Thread t3 = new Thread(apple, "Small C");
        //Open thread
        t1.start();
        t2.start();
        t3.start();
    }
}

2.2.3 advantages and disadvantages of synchronized

Advantages: it ensures the synchronous operation of multithread concurrent access and avoids thread safety problems

Disadvantages: the performance of synchronized method / code block is lower

Suggestion: minimize the scope of synchronized

3 . summary

3.1 talk about the difference between process and thread

Process: an application program of a computer There can be multiple threads in a process

Thread: a task in a process Multiple processes can share resources

3.2 how many threads are there after a Java program starts? What is their role?

A Java program starts with at least two threads

  1. Main thread - when the main method, that is, the mian method, runs, the JVM generates it automatically
  2. Background thread - garbage collection

3.3 how many ways to customize threads? What is the difference between them?

There are two ways to customize threads: 1 Inheritance method 2 Implementation mode

Difference: the inheritance method is easy to operate. Only static modification can share the same resource. However, because Java is single inheritance, if Thread is inherited, there can be no other direct parent class

Implementation method: it will be complex in operation, and thread. Com should be used Currentthread() to obtain the reference of the current thread. You can directly share the same resource. Because it uses an interface, you can inherit other classes and implement other interfaces

3.4 talk about the life cycle of threads and the transformation relationship between programs in different states

First new means that after a new thread is created, it will become a runnable state. The runnable state is divided into two types: one is ready and the other is running When we use the start method, we will enter the ready state. When the CPU schedules to this thread, we will enter the running state In the running state, the thread in the running state may become blocked for some reasons. For example, after sleep() and wait(), the thread is in the blocking state. At this time, other mechanisms are needed to wake up the thread in the blocking state, such as calling notify or notifyAll() methods The thread terminates when it completes execution or throws an exception

3.5 talk about the difference between synchronous and asynchronous

Synchronization: it is also concurrency, that is, accessing the same resource together

Asynchronous: alternate access to the same resource

3.6 talk about your understanding of the problems caused by multithreaded concurrent access

When the method is not in place in one step, there may be some problems. For example, three people eat apples. The number of apples eaten by the first person should be - 1, but A has not finished the operation, and the resources are robbed by B. the apple eaten by B is also the one in A's hand, which will cause problems

3.7 how to solve the problems caused by multithreading concurrent access?

Apply synchronization lock to the required code block, that is, use synchronization method or synchronize code block Let the thread finish in order

Posted by sader on Fri, 20 May 2022 18:08:23 +0300