Summary of javaSE multi-threaded notes

Concept of process and thread

Process: A running program is an independent unit for resource allocation and calling in the system. Each process has its own memory space and system resources.
Thread: It is a single sequential control flow in a process and an execution path. If a process has only one execution path, it is called a single-threaded program. If a process has multiple execution paths, it is called a multithreaded program.

Methods to implement multi-threaded programs:

  • Inherit the Thread class
 public class MyThread extends Thread {
    
    
	@Override
	public void run() {
    
    
		for (int x = 0; x < 100; x++) {
    
    
			System.out.println(getName() + ":" + x);
		}
	}
}
public static void main(String[] args){
    
    
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();
        thread1.start();
        thread2.start();
    }

Related methods:
public static void yield(): Suspend the currently executing thread object and execute other threads. Make the execution of multiple threads more harmonious, but it cannot guarantee one person once.
public final void stop(): Stop the thread. It is obsolete, but it can still be used.
public void interrupt(): Interrupt the thread. Terminate the state of the thread and throw an InterruptedException.

  • Implement interface
public class MyRunnableDemo {
    
    
    public static void main(String[] args){
    
    
        MyRunnable runnable1 = new MyRunnable();
        Thread thread1 = new Thread(runnable1, "刘雨昕");
        Thread thread2 = new Thread(runnable1, "许佳琪");

        thread1.start();
        thread2.start();
    }
}
public class MyRunnable implements Runnable{
    
    
    @Override
    public void run() {
    
    
        for(int i=0; i<100; i++){
    
    
            System.out.println(Thread.currentThread().getName()+ ":" + i);
        }
    }
}

Thread life cycle

  1. New
  2. Ready
  3. run
  4. block
  5. death
    Insert picture description here

Practical application (simulating ticket sales)

public class SellTicket extends Thread{
    
    
    private static int tickets = 100;

    @Override
    public void run() {
    
    
        while (tickets >= 0){
    
    
            try {
    
    
                Thread.sleep(100);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            System.out.println(getName() + ":" + tickets--);
        }
    }
}

public class SellTicketDemo {
    
    
    public static void main(String[] args){
    
    
        SellTicket thread1 = new SellTicket();
        SellTicket thread2 = new SellTicket();
        SellTicket thread3 = new SellTicket();
        thread1.setName("窗口一");
        thread2.setName("窗口二");
        thread3.setName("窗口三");

        thread1.start();
        thread2.start();
        thread3.start();
    }
}

Problems:

  1. The same ticket has been sold many times.
    Insert picture description here
    Reason: One operation of the CPU must be atomic
    System.out.println(getName() + ":" + tickets–); This statement is divided into three atomic operations, one is first Record the previous value, then put the ticket–, and then output the previous value.
    Process analysis: Assuming that the current tickets are 94 and thread1 is running, when System.out.println(getName() + ":" + tickets–) is executed, the previous value is recorded as 94. At this time, thread2 grabs the time slice and executes System. .out.println(getName() + “:” + tickets–) records the previous value as 94, and thread3 grabs the time slice and executes System.out.println(getName() + “:” + tickets–) to record The previous value was 94, then ticket–, and then output 94. At this time, thread2 grabbed the time slice. At this time, the value recorded by thread2 was 94 (but the actual value has become 93), ticket–, and then output 94. This brings errors.
  2. There are negative votes.
    Insert picture description here
    Reason: Randomness and delay
    process analysis: thread1 grabs the time slice and enters the run program sleep. At this time, thread2 grabs the time slice, enters the run program and sleeps. At this time, thread3 grabs the time slice and enters the run program sleep , Thread123 wakes up in turn, executes System.out.println(getName() + ":" + tickets–), and the situation shown in the picture appears.
    Solution:
    The thread safety problem occurs as follows:
    A: It is a multi-threaded environment
    B: There is shared data
    C: There are multiple statements that operate on shared data.
    AB cannot control. For C, you can lock multiple operation statements. That is, thread synchronization.
    note:
  •  	同步可以解决安全问题的根本原因就在那个对象上。该对象如同锁的功能。
    
  •  	多个线程必须是同一把锁。
    
public class SellTicket extends Thread{
    
    
    private static int tickets = 100;
    //创建锁对象
    private static Object obj = new Object();

    @Override
    public void run() {
    
    
        synchronized (obj){
    
    
            while (tickets >= 0){
    
    
                try {
    
    
                    Thread.sleep(100);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
                System.out.println(getName() + ":" + tickets--);
            }
        }
    }
}
public class SellTicketDemo {
    
    
    public static void main(String[] args){
    
    
        SellTicket thread1 = new SellTicket();
        SellTicket thread2 = new SellTicket();
        SellTicket thread3 = new SellTicket();
        thread1.setName("窗口一");
        thread2.setName("窗口二");
        thread3.setName("窗口三");

        thread1.start();
        thread2.start();
        thread3.start();
    }
}

This is achieved by inheriting the thread class, in which tickets and obj must be static variables to ensure that a class shares a ticket and obj.
But this will cause deadlock problems, such as:

public class DieLock extends Thread{
    
    
    private boolean flag;
    private static final Object obj1 = new Object();
    private static final Object obj2 = new Object();

    public DieLock(boolean flag) {
    
    
        this.flag = flag;
    }

    public DieLock() {
    
    
    }

    @Override
    public void run() {
    
    
        if(flag){
    
    
            synchronized (obj1){
    
    
                System.out.println("if obj 1");
                synchronized (obj2){
    
    
                    System.out.println("if obj 2");
                }
            }
        }else {
    
    
            synchronized (obj2){
    
    
                System.out.println("if obj 2jiojoiji");
                synchronized (obj1){
    
    
                    System.out.println("if obj 1hiughjhjkhk");
                }
            }

        }
    }
}

```java
public class DieLockDemo {
    
    
    public static void main(String[] args){
    
    
        DieLock lock1 = new DieLock(true);
        DieLock lock2 = new DieLock(false);

        lock1.start();
        lock2.start();
    }
}

The correct result is: Insert picture description here
but there will be a deadlock situation, such as: Insert picture description here
analysis: this is because lock2 locked obj2 and printed out "if obj 2", lock1 grabbed the time slice and locked obj2 and printed out "if obj 1", then connect Then it cannot be executed because both locks are locked.

Thread group and thread pool

Thread group: Java uses ThreadGroup to represent the thread group, which can classify and manage a thread and allows the program to directly control the thread group.
Thread pool: The cost of starting a new thread for a program is relatively high because it involves interacting with the operating system. The use of thread pool can improve performance, especially when a large number of threads with a short lifetime are to be created in the program, the thread pool should be considered.

  • After each thread code in the thread pool ends, it will not die, but will return to the thread pool to become idle again, waiting for the next object to use.
  • Before JDK5, we had to manually implement our own thread pool. Starting from JDK5, Java has built-in support for thread pool

Related knowledge points

Concurrency and parallelism:
Parallelism refers to logically occurring simultaneously, which means that multiple programs are running at the same time at a certain time.
Concurrency refers to physical simultaneous occurrence, which refers to multiple programs running at a certain point in time.

The operating principle of the java program: The
JVM is started by the java command, and the JVM startup is equivalent to starting a process, which creates a main thread and calls the main method.
Realize multi-threaded programs:
Threads are dependent on processes. A process should be created first. The process is created by the system, so the system function must be called to create a process. However, Java cannot directly call system functions, so there is no way to directly implement multithreaded programs. But Java can call programs written in C/C++ to implement multithreaded programs. C/C++ calls system functions to create processes, and then Java calls such things, and then provides some classes for us to use to realize multi-threaded programs.
Thread safe class:
StringBuffer
Vector
Hashtable

Guess you like

Origin blog.csdn.net/go_to_study/article/details/109296471