Basic skills of java multithreading

1. What is a process? What is a thread

Compared with the exe program, the process is a dynamic concept, which can be said to be a running program. A process is the basic unit of resource (CPU, memory, etc.) allocation. A
thread can be understood as a subtask that runs independently in a process. It is the smallest unit when the program is executed.
For example , when the qq.exe program is running, many subtasks are also running at the same time, such as adding friends, videos, downloading files, and listening to music. The
process Fuzhou wants the operating system to apply for resources. In a process, multiple threads can share the same memory or file resources in the process

We can analyze it from the perspective of jvm: it Insert picture description here
can be seen that there can be multiple threads in a process, and multiple threads share the process's heap and method area (metaspace after JDK1.8) resources, but each thread has its own Program counter, virtual machine stack and local method stack.

2. The advantages of multi-threading

The use of multithreading is the use of asynchronous can perform multiple tasks at the same time

3. When to use multithreading

1). Blocked. Once there is a blocking phenomenon in the system, you can use multi-threading technology to improve operating efficiency according to the actual situation
2). Dependence. The business is divided into two execution processes, namely A and B. When the A service is blocked, the execution of the B service does not depend on the execution result of the A service

4. How to create a thread

Before learning how to create a thread, take a look at the declaration structure of the thread class:

public class Thread implements Runable

Due to the characteristics of java on inheritance-does not support multiple inheritance, so in order to better extend the class, we generally use the implementation of the runnable interface. That is, while implementing the inheritance. But the function of creating threads in the two ways is the same, there is no essential difference

Methods of creating threads:
1. InheritanceThreadmethod

new Thread(()->{
    
    },"").start();

2. RealizeRunnableinterface

public class MyThread2 implements Runnable {
    
    //实现Runnable接口
  public void run(){
    
    
  //重写run方法
  }
}
public class Main {
    
    
  public static void main(String[] args){
    
    
    //创建并启动线程

    MyThread2 myThread=new MyThread2();

    Thread thread=new Thread(myThread);

    thread().start();

    //或者    new Thread(new MyThread2()).start();

  }

}

Extension: The strat() method performs the following steps:

1. Tell the operating system to create a Thread through jvm
2. The operating system opens up memory and uses the createThread() function in the Windows SDK to create a Thread thread object.
3. The operating system schedules the Thread object to determine the timing of execution. 4. Thread
is successfully executed in the operating system

3. UseThread Pool

4. RealizeCallableInterface, rewrite the == call() == method, then wrap it into java.util.concurrent.FutureTask, and then wrap it into Thread
Callable: a thread with a return value can cancel the thread and judge whether the thread has been executed.

public class Main {
    
    
    public static void main(String[] args) throws Exception {
    
    
    	 // 将Callable包装成FutureTask,FutureTask也是一种Runnable
        MyCallable callable = new MyCallable();
        //包装线程执行目标,因为Thread的构造函数只能接受Runnable接口的实现类,而FutureTask类实现了Runnable接口
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        //传入线程执行目标,实例化线程对象
        new Thread(futureTask).start();

        // get方法会阻塞调用的线程
        Integer sum = futureTask.get();
        System.out.println(Thread.currentThread().getName() + Thread.currentThread().getId() + "=" + sum);
    }
}


class MyCallable implements Callable<Integer> {
    
    

    @Override
    public Integer call() throws Exception {
    
    
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId() + "\t" + new Date() + " \tstarting...");
//具体重写call方法
        Thread.sleep(5000);

        System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId() + "\t" + new Date() + " \tover...");
        return sum;
    }
}

Callable is also a functional interface

@FunctionalInterface
public interface Callable<V> {
    
    
    V call() throws Exception;
}

FutureTask

public class FutureTask<V> implements RunnableFuture<V> {
    
    
	// 构造函数
	public FutureTask(Callable<V> callable);
	
	// 取消线程
	public boolean cancel(boolean mayInterruptIfRunning);
	// 判断线程
	public boolean isDone();
	// 获取线程执行结果
	public V get() throws InterruptedException, ExecutionException;
}

RunnableFuture

public interface RunnableFuture<V> extends Runnable, Future<V> {
    
    
    void run();
}

The relationship between the above classes:Insert picture description here

Comparison of three ways:

  • Thread: Inheritance method, it is not recommended, because Java is single inheritance. After inheriting Thread, there is no way to inherit other classes, which is not flexible enough.
  • Runnable: Implementation of the interface, more flexible than the Thread class, without the limitation of single inheritance
  • Callable: Thread and Runnable are both overridden run() methods and have no return value. Callable is an overridden call() method and has a return value and can use the FutureTask class to determine whether the thread has been executed or cancel the thread execution
  • Runnable is used when the thread does not need the return value, and Callable is used when the return value is needed. Under normal circumstances, the thread body code is not directly placed in the Thread class, and the thread is generally started through the Thread class
  • The Thread class implements Runnable, Callable is encapsulated into FutureTask, FutureTask implements RunnableFuture, RunnableFuture inherits Runnable, so Callable is also a kind of Runnable, so the three implementation methods are essentially Runnable implementations

5. Thread scheduling is random

6. Thread life cycle

	/**
     * 线程生命周期中的的六种状态
     * NEW:还没有调用start()的线程实例所处的状态
     * RUNNABLE:正在虚拟机中执行的线程所处的状态
     * BLOCKED:等待在监视器锁上的线程所处的状态
     * WAITING:等待其它线程执行特定操作的线程所处的状态
     * TIMED_WAITING:等待其它线程执行超时操作的线程所处的状态
     * TERMINATED:退出的线程所处的状态
     * 给定时间点,一个线程只会处于以下状态中的一个,这些状态仅仅是虚拟机层面的线程状态,并不能反映任何操作系统中线程的状态
     */
    public enum State {
    
    
        //还没有调用start()开启的线程实例所处的状态
        NEW, 
        //正在虚拟机中执行或者等待被执行的线程所处的状态,但是这种状态也包含线程正在等待处理器资源这种情况
        RUNNABLE,
        // 等待在监视器锁上的线程所处的状态,比如进入synchronized同步代码块或同步方法失败
        BLOCKED,
        // 等待其它线程执行特定操作的线程所处的状态;比如线程执行了以下方法: Object.wait with no timeout、Thread.join with no timeout、 LockSupport.park
        WAITING,
       // 等待其它线程执行超时操作的线程所处的状态;比如线程执行了以下方法: Thread.sleep、Object.wait with timeout
       //Thread.join with timeout、LockSupport.parkNanos、LockSupport.parkUntil
        TIMED_WAITING,
        //退出的线程所处的状态
        TERMINATED;
    }

Insert picture description here
Detailed description of the status:
1.Initial state (NEW)
A thread class can be obtained by implementing the Runnable interface and inheriting from Thread. When an instance of new comes out, the thread enters the initial state.
2.Runnable The thread enters this state after calling the start() method. The state includes three situations:

  1. Ready state: waiting for the CPU to allocate time slices [1. Ready state just means that you are qualified to run, and the scheduler does not pick you up, you will always be in the ready state. 2. The start() method of the thread is called, and the thread enters the ready state.
  2. Running state: enter the Runnable method to execute the task
  3. Blocking state: the state when BIO executes a blocking io stream

3.Blocked
The blocking state when the lock is not acquired (the blocking state is the state when the thread is blocked when entering the method or code block modified by the synchronized keyword (acquiring the lock))
4.Waiting (WAITING)
The state after calling wait(), join() or LockSupport.park and Thread.sleep(). Threads in this state will not be allocated CPU execution time, they have to wait to be awakened explicitly, otherwise they will wait indefinitely.
5.Timeout waiting (TIMED_WAITING)
The state after calling sleep(time), wait(time), join(time) and other methods. Threads in this state will not be allocated CPU execution time, but there is no need to wait indefinitely for being awakened by other threads. They will automatically wake up after a certain time.
6.Termination status (TERMINATED)
The state after the thread finishes execution or throws an exception.
For example: 1. When the thread's run() method is completed, or the main thread's main() method is completed, we consider it terminated. This thread object may be alive, but it is no longer a separate thread of execution. Once the thread is terminated, it cannot be reborn. 2. Invoking the start() method on a terminated thread will throw java.lang.IllegalThreadStateException.

7. Thread priority

Thread In the class, the following attributes are used to represent the priority.

private int priority;

We can set the new priority by ==setPriority(int newPriority)==, and get the priority of the thread by getPriority().
Thread initializes the source code of priority

Thread parent = currentThread();
this.priority = parent.getPriority();

It turns out that the default priority of a thread is to inherit the priority of the parent thread.
Strictly speaking, the default priority of the child thread is the same as that of the parent thread, and the default priority of the Java main thread is 5.
Three priority levels are defined in Java, namelyLowest priority (1), normal priority (5), highest priority (10), The code is as follows. The Java priority range is [1, 10], setting the priority of other numbers will throw an IllegalArgumentException.
note:The order of code execution has nothing to do with thread priority. High-priority threads are more likely to get CPU resources first than low-priority threads. High priority runs fast

8. The basic method of threading

Insert picture description here

1.currentThread() method: which thread is calling the return code (get the current thread)

public class CurrentThreadTest {
    
    
    public static void main(String[] args) {
    
    
        MyThread myThread = new MyThread();
        myThread.start();
    }
}
class MyThread extends Thread{
    
    
    public MyThread(){
    
    
        System.out.println("构造方法的打印:"+Thread.currentThread().getName());
    }
    public void run(){
    
    
        System.out.println("run方法的打印:"+Thread.currentThread().getName());
    }
}

Output result: Insert picture description here
It can be seen from the execution result: The constructor of the MyThread.java class is called by the main thread, and the run method is called by the thread of Thread-0. The
2.isAlive() method of 1 is to determine whether the current thread is alive.

public class IsAliveTest {
    
    
    @SneakyThrows
    public static void main(String[] args) {
    
    
        MythreadIsAlive myThread = new MythreadIsAlive();
        System.out.println("begin =="+myThread.isAlive());
        myThread.start();
        System.out.println("end =="+myThread.isAlive());
        //主线程睡眠1s 目的:让子线程结果
        Thread.sleep(1000);
        System.out.println("睡玩之后end =="+myThread.isAlive());
    }
}
class MythreadIsAlive extends Thread{
    
    

    @Override
    public void run() {
    
    
        System.out.println("run="+this.isAlive());
    }
}

Output result: Insert picture description here
So what isActive statusWhat? The state where the thread has been started and not yet terminated is the active state
3. sleep (Long millis) method: sleep the current "executing thread" within the specified time (milliseconds), this executing thread refers to this.currentThread() The returned thread
4.stackTraceElement[] getStackTrace() method: returns a stack trace element group that represents the thread. If the thread has not been started or has terminated, the method returns a zero-length array. If the returned array is not zero length, its first element represents the top of the stack, which is the latest method call in the array. The last element represents the bottom of the stack, which is the oldest method call in the array
5.static void dumpStack() method: the function is to output the stack trace information of the current thread to the standard error stream.
6.static Map<Thread,StackTraceElement[]> getAllStackTraces() method: the
function is to return a map of the stack traces of all active threads
7.getId() method: get the unique identifier of the thread
8.yield(): give up the current cpu Resource, give it to other tasks to occupy the CPU execution time, but the time of giving up is uncertain. It may just give up and get the CPU time slice immediately.
9.interrupt(): A stop mark is marked in the current thread, It is not really stopping the thread.
10.interrupted(): Test whether the current thread has been interrupted. After execution, it has the function of clearing the status flag to false //public static boolean interrupted()
11.isInterrupted(): Test whether the thread has been interrupted, But does not clear the status flag //public boolean isInterrupted()
12.suspend(): Suspend the thread
13.resume(): Resume the thread

Guess you like

Origin blog.csdn.net/f_a_ker/article/details/114003842
Recommended