Climbing the ladder: Java multithreading foundation

Learning resources are organized from: Station B "Crazy God Talk"

Java multithreading basics

Knowledge point segmentation:

  1. Multithreading overview
  2. Thread realization: inherit Thread, realize Runnable, realize Callable, Lamdb expression
  3. Concurrency
  4. Some operations of threads
  5. Thread lock
  6. Advanced topics

1. Overview of multithreading

Process

A process can have multiple threads.

Thread

  • Thread is independent execution path
  • When the program is running, there is no thread created by itself, and there will be multiple threads in the background, such as the main thread and gc thread.
  • main() is called the main thread, the entrance of the system, used to execute the entire program
  • In a process, if multiple threads are opened, the running of the threads will be arranged and scheduled by the scheduler. The scheduler is related to the operating system Jinmi, and the order cannot be interfered by human intervention.
  • When operating on the same resource, there will be resource grabbing problems, and concurrency control needs to be added
  • Threads will bring additional overhead such as cpu scheduling time, concurrency control
  • Each thread interacts in its own working memory. Improper memory control will cause data inconsistency

2. Implementation of threads

Inherit Thread

The custom class inherits Thread and overrides the run() method. Threads are not necessarily executed immediately and are scheduled by the CPU.

Call: instantiate a custom class, execute run() or start();

  • The run method will return to the main thread after execution;
  • The start method is executed "simultaneously" with the main thread

Disadvantages: limitations of single inheritance

Insert picture description here

Implement Runnable (emphasis)

Create a thread class, implement the Runnable interface, and implement the run method. Create Thread, pass this thread class as a parameter, and start it.

Call: instantiate the thread class, then create a Thread object, pass the thread class into the Thread constructor, and execute the start method of the Thread object.

Simulate ticket grabbing system, multi-threaded manipulation of the same resource

/**
 * 抢车票
 * @author: stone
 * @create: 2020-08-13 15:14
 */
public class TestRunnable01 implements Runnable {

    //车票总数
    private int ticketTotal = 50;

    @Override
    public void run() {
        while (true) {
            if (ticketTotal <= 0) {
                break;
            }
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "抢到第" + ticketTotal-- + "票");
        }
    }

    public static void main(String args[]){
        TestRunnable01 ticket = new TestRunnable01();

        new Thread(ticket,"小石").start();
        new Thread(ticket,"周杰伦").start();
        new Thread(ticket,"黄牛").start();
    }
}
#结果
周杰伦抢到第50票
黄牛抢到第49票
小石抢到第49票
黄牛抢到第47票
周杰伦抢到第48票
小石抢到第46票
周杰伦抢到第45票
......

Implement Callable (understand)

  1. To implement the Callable interface, the return value type is required
  2. Rewrite call method, need to throw an exception
  3. Create a target audience
  4. Create an execution service: ExecutorService ser=Executors.newFixedThreadPool(1);
  5. Submit for execution: Funture result1=ser.submit(t1);
  6. Get the execution result: boolean r1 = result1.get();
  7. Shut down the service: ser.shutdownNow();

Advantages: contain return value, can throw exception;

Lamda expression

Concept: simplify the code, remove temporary variables, and make the core part of the code more prominent.

Functional interface: An interface containing only one abstract method is called a functional interface.

Evolution process:

  1. Custom class implements functional interface
  2. Write internal classes to implement functional interfaces
  3. Static inner class implements functional interface
  4. Anonymous inner class, instantiate the interface directly and implement abstract methods
  5. lambda expression, write method body
Thread thread = new Thread(()->{
	System.out.println("线程体");
});

3. Static proxy

Agency model concept:

  • It is true that the object and the proxy object must have an interface in advance
  • Proxy objects
  • advantage:
    • Proxy objects can do many things that real objects cannot do
    • Really the subject is focused on doing his own thing
//真实类实现Runnable接口
class TrulyObj implement Runnable(){}

//线程类实现了Runnable接口 (代理)
class Thread implement Runnable(){}

//使用代理类去执行真实类
new Thread(trulyObj).start();
//start也是执行了run方法,而run方法在真实类中重写了

4. Thread operation

Thread life cycle:

Insert picture description here

Common API:

  • Stop the thread:
/**
 * 测试stop
 * 1、推荐使用flag标示,让线程自行停止,不建议死循环
 * 2、推荐使用次数控制
 * 3、不推荐使用stop()和destroy()
 * @author: stone
 * @create: 2020-08-13 16:48
 */
public class TestStop implements Runnable {

    private boolean flag = true;

    public void setFlag(boolean f) {
        if(this.flag){
            System.out.println("子线程停止======");
        }
        this.flag = f;
    }

    @Override
    public void run() {
        while (flag) {
            System.out.println("子线程在跑----------------");
        }
    }

    public static void main(String args[]) {
        TestStop testStop = new TestStop();
        new Thread(testStop).start();

        for (int i = 0; i < 30; i++) {
            if (i >= 10) {
                testStop.setFlag(false);
            }
            System.out.println("主线程在跑:" + i);
        }
    }
}
  • Thread sleep

    Thread.sleep(time);

    • Sleep the current thread for the specified number of milliseconds
    • There is an exception InterruptedException
    • The program enters the ready state after the sleep time is reached
    • Sleep can simulate test network delay, countdown, etc. (increasing the probability of event occurrence)
    • Every object has a lock, sleep will not cast a lock
  • Thread Polite

    Thread.yield();

    • Polite thread, let the currently executing thread pause, but not block
    • Turn the thread from the running state to the ready state and make it go to the queue to get the CPU
    • Politeness just allows the CPU to reschedule, not necessarily suspending the current thread to execute other threads
  • Thread jump

    thread.join();

    • After the execution of this thread is completed, other threads are executed, and other threads are blocked

Insert picture description here

  • Thread state

    Thread.State enum

    thread.getState();

    • NEW thread is not started
    • RUNNABLE thread runs in JVM
    • BLOCKED is blocked waiting
    • WAITING waiting for another thread to perform a specific action
    • TIMED WAITNG thread waits for the specified time
    • TERMINATED is over
  • Thread priority
    • Java provides a thread scheduler to monitor all threads that enter the ready state after startup in the program. The thread scheduler decides which thread to schedule first to execute according to the priority.

    • The priority of the thread is expressed in numbers, ranging from 1 to 10

      • Thread.MIN_PRIORITY = 1;
      • Thread.MAX_PRIORITY = 10;
      • Thread.NORM_PRIORITY = 5;
    • Get priority: thread.getPriority();

    • Set priority: thread.setPriority(int x);

    • The priority of the main method is 5;

    • Set the priority first, then start;

    • High priority does not necessarily start early

  • Daemon
    • Threads are divided into user threads and daemon threads
    • The virtual machine must ensure that the user thread finishes execution
    • The virtual machine does not need to wait for the daemon thread to finish executing
    • Examples: background recording operation log thread, monitoring memory thread, garbage collection waiting thread

thread.setDaemon(true);//Set as a daemon thread

5. Thread synchronization

Concurrency: multiple threads operate the same object at the same time

Queue and lock synchronized

Queuing, when a thread obtains an exclusive lock on an object and monopolizes resources, other threads must wait for the user to release the lock before proceeding

  • A thread holding a lock will cause other threads to hang;

  • Under multi-thread competition, locking and releasing locks will cause more context switching and scheduling delays, causing performance problems

  • If a high-priority thread is waiting for a low-priority thread to release the lock, it will cause priority inversion and cause performance problems

  • Synchronized block: syschronized(Obj ){}

  • Obj calls it a sync monitor

    • Obj can be any object, but it is recommended to use shared resources as a synchronization monitor
    • There is no need to specify a synchronization monitor in the synchronization method, because the synchronization monitor of the synchronization method is this class of the current object itself
  • Synchronization monitor execution process

    1. The first thread accesses, obtains the lock of the synchronization monitor, and executes the code
    2. Access by the second thread, waiting for the first thread to release the lock of the synchronization monitor, unable to access
    3. After the first thread is executed, the lock of the synchronization monitor is released
    4. The second thread accesses, obtains the lock of the synchronization monitor, and executes the code

6. Deadlock

Multiple threads each occupy some shared resources, and wait for the resources occupied by other threads to execute each other, causing two or more threads to wait.

The cause of deadlock:

  • Mutually exclusive conditions: a resource can only be executed by one process at a time (lock)
  • Request and hold conditions: when a process is blocked by requesting resources, keep the acquired resources
  • Non-deprivation conditions: the resources already acquired by the process cannot be deprived before they are used up
  • Circulation waiting condition: a kind of cyclic waiting resource relationship is formed between several processes.

7. Lock (lock)

  • Starting from JDK5.0, Java provides a more powerful thread synchronization mechanism-to achieve synchronization by explicitly defining synchronization lock objects. Synchronization locks use the Lock object as
  • The java.util.concurrent.locks.Lock interface is a tool for controlling multiple threads to access shared resources. The lock provides exclusive access to shared resources. Only one thread can lock the Lock object at a time, and the thread starts to access the shared resource. The Lock object should be obtained before the resource
  • The ReentrantLock class implements Lock, which has the same concurrency and memory semantics as synchronized. In the realization of thread-safe control, ReentrantLock is commonly used, which can display locks and release locks.
//定义lock锁
private final ReentrantLock look = new ReentrantLock();

try{
	lock.lock();//加锁
	......
}finnally{
	lock.unlock();//解锁
}

Comparison of synchronized and Lock

synchronized Lock
Implicit lock, automatically cast out of scope Display lock, manually open and close
JVM will spend less time to schedule threads, better performance
Better scalability, providing more sub-categories

8. Thread communication

wait();//Hang up and wait until other threads notify, wait will release the lock

wait(long timeout);//Specify the number of milliseconds to wait

notify();//Wake up a thread in a waiting state

notifyAll();//Wake up all threads calling the wait() method on the same object, and the higher priority is scheduled first

PS: All methods of the Object class can only be used in synchronous methods or synchronous code blocks, otherwise an exception IllegalMonitorStateException will be thrown

Concurrent collaboration model: "producer/consumer model"

Producer-> Product -> Consumer

Management method

  • Producer: The module responsible for producing data (methods, objects, threads, processes)

  • Consumer: the module responsible for processing data (methods, objects, threads, processes)

  • Buffer: Consumers cannot directly use the producer’s data, and a "buffer" is established in the middle

    The producer puts the product into the buffer, and the consumer takes the product from the buffer

Producer --> Buffer --> Consumer

Semaphore method

By operating a mark together as a switch, communication between threads is realized.

The producer completes the production, opens the label, and informs the consumer to use the product.

After the consumer finishes using the product, the label is turned off and the producer is notified to produce the product.

flag

9, thread pool

Create multiple threads, put them in the thread pool, get them directly when used, and put them back into the thread pool after use

advantage:

  • Reduce resource consumption and improve response speed (reduce thread creation time and machine resources)
  • Facilitate thread management
    • corePoolSize: the size of the core pool
    • maximumPoolSize: Maximum number of threads
    • keepAliveTime: the most often alive time when the thread has no task

Use thread pool:

  • JDK5.0 provides thread pool API: ExecutorService and Executors
  • ExecutorService: The real thread pool interface. Common subclass ThreadPoolExecutor
    • void execute(Runnable command): execute task/command without return value, generally used to execute Runnable
    • Future submit (Callable task): execute task, return value, generally used to execute Callable
    • void shutdown(): close the connection pool
  • Executors: Tool classes, thread pool tool classes, used to create and return different types of thread pools .
ExecutorService executorService = Executors.newFixedThreadPool(10);

Guess you like

Origin blog.csdn.net/qq845484236/article/details/107992915