Thread class and commonly used methods

First, the common construction method of Thread

method illustrate
Thread() Create thread object
Thread(Runnable target) Create thread objects using Runnable objects
Thread(String name) Create a thread object and name it
Thread(Runnable target,String name) Use Runnable objects to create thread objects and name them

Regarding the first two methods, I used them in the previous thread creation introduction.

There are basically two ways to create a thread:

  1. Create a 继承自 Thread 类subclass, override the run method in Thread, and call the start method
  2. Create a 实现 Runnable 接口class that overrides the run method in Thread. Create a Thread instance, set the instance of the class that implements the Runnable interface written by yourself, and call the start method

Constructors three and four just add a parameter named thread object on the basis of the previous two construction methods, which is convenient for programmers to debug.

Code (take construction method 4 as an example):

public class func7 {
    
    
    public static void main(String[] args) {
    
    
        Thread thread = new Thread(() ->{
    
    
            while (true) {
    
    
                System.out.println("This is my Thread");
                try {
    
    
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        },"myThread");
        //此处用 lambda 表达式代替 Runnable 实例,更加简洁,添加了一个参数指定thread线程的名字
        thread.start();
        while (true) {
    
    
            System.out.println("my main");
            try {
    
    
                Thread.sleep(1000);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

jconsoleProgrammers can visually view the threads created here through the tools that come with the JDK

step one:

After running the program, find your own jdk path -> bin -> jconsole.exe

insert image description here

Step 2: Double-click the exe file. Select Local Processes, where Java processes are listed. We can see our program func7, click on it. In the menu bar, select the thread column

insert image description here

Step 3: View thread information

insert image description here

On the left side, you can select the thread to be viewed. You can see the main thread main and the newly created thread myThread. If there is no renaming operation, the newly created thread name will be called Thread-0, Thread-1, which is not convenient to view. .

The right side shows the state of the thread at the moment it was read, and the stack trace shows where the code was executed.

2. Common properties of Thread

Attributes method
ID getId()
name getName()
state getState()
priority getPriority()
Whether it is a background thread isDaemon ()
Is it alive isAlive()
Is it interrupted isInterrupted()

explain:

  1. The unique identifier of the thread is线程 Id

  2. 名称It is reflected in the above case, which provides convenience for debugging

  3. 状态Indicates the current situation of the thread. In the above case, the thread enters the blocked state because the sleep method is called.

  4. 优先级Indicates the difficulty of the thread being scheduled, higher ones are easier to be scheduled to

  5. judgment 是否为后台线程. If it is a background thread, then the background thread will not affect the end of the java process; if it is a non-background thread, the JVM will wait until all non-background threads are executed before ending the operation, so it will affect the end of the total process

  6. 是否存活Is the method to determine whether the thread still exists. When a Thread instance object is created, the thread is not necessarily created, and the start method needs to be called to actually create the thread. When the run method in the thread is executed, the thread ends and is destroyed, and the created instance object has not been destroyed and recycled. so,创建出的实例对象和线程的生命周期是不完全相同的

    In the thread's state, states other thanNEW and are aliveTERMINATED

Code:

public class func8 {
    
    
    public static void main(String[] args) {
    
    
        Thread t = new Thread(()->{
    
    
            for (int i = 0;i < 5;i ++) {
    
    
                System.out.println("新线程~");
                try {
    
    
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        },"newThread");
        System.out.println("新线程状态:" +t.getState());
        //创建了对象,没创建线程
        t.start();
        System.out.println("新线程状态:" +t.getState());
        //创建了线程
        System.out.println("新线程Id:"+t.getId());
        System.out.println("新线程名称:"+t.getName());
        System.out.println("新线程是否为后台线程:" + t.isDaemon());
        System.out.println("新线程是否被中断:" + t.isInterrupted());
        System.out.println("新线程优先级:" + t.getPriority());
        System.out.println("主线程名称:"+Thread.currentThread().getName());
        while (t.isAlive()) {
    
    } //当t线程还存在时,主线程就搁这儿循环着,直到线程结束
        System.out.println("新线程状态:" +t.getState());//线程结束
    }
}

result:

insert image description here

3. Create a thread

Creating an object of the Thread class does not mean that the thread is created start() 方法才是真正的在操作系统内部创建一个新的线程. By overriding the run method to describe the tasks that need to be executed, multi-threaded operation is truly realized.

Fourth, interrupt the thread

Method 1: 手动设置标志位, as a condition for interrupting the thread

public class func9 {
    
    
    private static Boolean flag = false;//手动设置的标志位 flag
    public static void main(String[] args) {
    
    
        Thread t = new Thread(() -> {
    
    
            while (!flag) {
    
    
                //flag 为真时停止循环
                System.out.println("myThread");
                try {
    
    
                    Thread.sleep(1000);//打印一次,阻塞一秒
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        });
        t.start();//创建了线程 t
        try {
    
    
            Thread.sleep(3000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        flag = true;
        //等3秒后,在主线程中将 flag 的值改成 true,从而使线程t循环条件不成立
    }
}

Method Two:使用 Thread 实例中的标志位

public class func10 {
    
    
    public static void main(String[] args) {
    
    
        Thread t = new Thread() {
    
    
            @Override
            public void run() {
    
    
                //通过 isInerrupted()判断标志位是否为true,为true说明线程要退出
                while (!this.isInterrupted()) {
    
    
                   System.out.println("my Thread");
                   try {
    
    
                       Thread.sleep(1000);
                   } catch (InterruptedException e) {
    
    
                       e.printStackTrace();
                       //System.out.println("完善工作");
                       //break;
                   }
               }
            }
        };
        t.start();//创建新的线程
        try {
    
    
            Thread.sleep(3000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        t.interrupt();
        //t线程运行3秒后,通过 interrupt() 方法将标志位设置为 true
    }
}

result:

insert image description here

It can be seen that when the flag bit is set to true after 3 seconds, and it is hoped that the t thread is interrupted and exited, the result is only an InterruptedException exception.

In fact, when the interrupt method is called, if the thread is in the ready state, it will directly modify the flag in the thread; if it is in the blocked state, it will cause an InterruptedException (because the sleep method is called, it is blocking, and the result is forcibly called woke up)

But after receiving the signal of interrupting the thread, an exception occurred, it just simply printed the exception, and did not respond to the exception, so the t thread continued to loop, as if the signal of interrupting the thread was just a reminder that the thread hit Just a log is done, as if you didn't hear it.

In fact, there is a reason for such a mechanism. If the interrupt method is called, the thread will be interrupted when it says it is interrupted. It is very unreasonable. At this time, it is not known where the thread is executing. , how to do the finishing work, it is up to the thread to decide when it will be destroyed

Therefore, we need to complete the work after catching the InterruptedException exception, and then jump out of the loop through break to end the thread

方法二和方法一相比更加好. Because after the interrupt flag in method 1 is modified, even if it is sleeping at the time, the current sleep time will be over, and the next round of judgment will be made, and then the thread will be interrupted. Method 2 Even in sleep, after receiving the interrupt signal, it will be woken up immediately, and the interrupt information will be received more timely.

result:

insert image description here

Five, thread waiting

Determines the join() 方法thread execution order (mainly controls the order of ending threads).

public class func11 {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    
        Thread t1 = new Thread(() -> {
    
    
           for (int i = 0;i < 3;i ++) {
    
    
               System.out.println("my Thread~~");
               try {
    
    
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
    
    
                   e.printStackTrace();
               }
           }
        });
        t1.start();
        //t1.join();
        for (int i = 0;i < 3;i ++) {
    
    
            System.out.println("my main!!");
            try {
    
    
                Thread.sleep(1000);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

result:

insert image description here

When the join method is not called, the main thread and the t1 thread are concurrent, and the result output is alternate. After calling the join method, the main thread will block and wait, and the content after the join method will not be executed until the t1 thread is executed.

For the join method without parameters, the condition for waiting for the end is that the t1 thread ends, and if it does not end, it will continue to die; this method can also take parameters, and the waiting time can be specified by parameters.

6. Get the thread reference

In the thread code, you need to obtain the instantiated object of the Thread class corresponding to the current thread to perform more operations.

Method 1: Pass 继承 Thread 类创建的线程, you can this get

The second method in the above interrupted thread is to obtain information about whether the current instance is interrupted through this.isInterrupted().

If the method of creating a thread is changed to the method of creating a Runnable instance, the current run method is not a method of the Thread class, and this points to a Runnable, so there is no way to obtain a Thread instance, and there is no way to use the methods in it.

Method 2: Through Thread 类的 currentThread() 方法, which thread calls this method, the instance object of which thread is returned

insert image description here

Seven, thread sleep

This method is often introduced in the front, that issleep 方法

Once the sleep method is called, the thread will block and wait, and the waiting time depends on the specified parameters

The operating system is scheduled in units of threads, each thread corresponds to a PCB, and these PCBs are organized through a doubly linked list

When the operating system schedules the PCB, 就绪队列it selects a PCB to execute on the CPU. When the executing thread calls the sleep method, the PCB will be moved to the 阻塞队列middle. When the sleep time is up, it will return to the ready queue. , ready to be executed

The join method will also generate blocking waiting. Just like the example of thread waiting, after the main thread executes the join method, it will go to the blocking queue and wait for the corresponding t1 thread to complete the execution before returning to the ready queue and ready to be executed. preparation

Eight, thread status

From the code case of the previous common attributes of Thread, it can be seen that the state of the thread is not only ready and blocked, but even blocking is divided into several blocking types

//线程的状态是一个枚举类型 Thread.State
//打印 Java 线程中的所有状态
public class func13 {
    
    
    public static void main(String[] args) {
    
    
        for (Thread.State state : Thread.State.values()) {
    
    
            System.out.println(state);
        }
    }
}

result:

insert image description here

  • NEW: Indicates that the object of the Thread class is created, but the thread has not been created, that is, the start method has not been called
  • RUNNABLE: ready state
  • BLOCKED: The state while waiting for the lock (look forward to the next blog on thread safety)
  • WAITING: Triggered by the wait method (look forward to the next blog)
  • TIMED_WAITING: Generated by the sleep method
  • TERMINATED: The thread has been executed, but the object of the Thread class still exists and has not been destroyed
    !

Guess you like

Origin blog.csdn.net/weixin_46103589/article/details/124077593