Basic usage of the Thread class of java thread

Xiaoyu explained how to create threads in detail in the previous blog. Java uses the Thread class to create multi-threads. However, for many people who have no relevant experience, it is difficult to understand the execution process of the operating system scheduling. We Take the following code as an example:

    public static void main(String[] args) {
    
    
        Thread t = new Thread(() -> {
    
    
            System.out.println("hello t");
        });
        //调用start(),创建一个新的线程
        t.start();
 
        System.out.println("hello main");
    }

When our java starts, it will create a main thread. At this time, the name of the main thread is main. Next, we execute the codes in the main thread. When we execute t.start(), the system will automatically Create a new thread for us, and automatically call the run() method in the thread for us. At this time, the run() method can be considered as an entry, and some important implementation logic will be implemented in it.

Let's take the above code as an example:

When we instantiate a thread and call the start() method , the main thread and the t thread are (concurrent + parallel) processes. Since multi-threading has a root of all evils - the preemption mechanism , it will cause us to be unable to predict that the program is prioritized Execute "hello t" or "hello main", and we are not sure who will end the task of the thread first. It may be that the main thread ends first, or the t thread ends first.

insert image description here

The creation of threads depends on the order of start , but when the tasks corresponding to specific threads are executed depends on the system scheduler.

1. The constructor of the Thread class

method illustrate
Thread() create thread object
Thread(Runnable target) Create thread object using Runnable object
Thread(String name) Create a thread object and name it
Thread(Runnable target,String name) Use the Runnable object to create a thread object and name it
Thread(ThreadGroup group,Runnable target) Threads can be used for group management, and the divided groups are thread groups

The explanation of the construction method is discussed in detail in this article, including how to create a thread, and the matters needing attention when creating a thread are listed here one by one. The creation of multi-thread and its precautions

2. Several common attributes of Thread

Attributes access method
ID getId()
name getName()
state getState()
priority getPriority()
Whether background thread isDaemon()
whether to survive isAlive()
Is it interrupted isInterrupted()

common attributes

(1) getid() : ID represents the identity of the thread. It is unique like our ID card. The method here obtains the identity of the thread in the JVM. There are many thread identities. In the kernel There is a logo on the PCB, and there is also a logo in the user-mode thread database (thread library of the operating system)

(2) getName() : Get the name of the current thread, mostly used for debugging.

(3) getState() : Get the state of the current thread, and the state represents a situation to which the thread currently belongs.

(4) getPriority() : In theory, threads with high priority are easier to be scheduled, but in fact there is no difference. It can be understood that you suggest that I do not go to bed late, but it is only a suggestion, I can not listen.

(5) isDaemon() : daemon is called a "guardian thread", and it can also be called a background thread. If it is a background thread, it will return true, and the foreground thread is false. We can understand the background thread in this way. When we open the qq app on our mobile phone , at this time qq is running in the foreground, but since we may switch to the Kuaishou app later, qq will come to the background to run at this time.

When a thread is created , it is the foreground thread by default . The foreground thread will prevent the exit of the process . The process can only exit after all the foreground threads are executed, but for the background process, it will not prevent the end of the process.

The JVM will not end running until all non-background processes of a process end.

(6) isAlive() : Whether it is alive, that is, whether the run() method ends.

public class Demo4 {
    
    
    public static void main(String[] args) {
    
    
        Thread t = new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                System.out.println("t 线程正在运行");
            }
        });
        System.out.println("t线程是否存活 "+t.isAlive());
        t.start();
        System.out.println("t线程是否存活 "+t.isAlive());

        try {
    
    
            Thread.sleep(1000);
            System.out.println("t线程是否存活 "+t.isAlive());
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }

    }
}

If the run of t has not run, isAlive is false;
if the run of t is running, isAlive is true;
if the run of t is finished, isAlive is false;

Results of the:

insert image description here

At this point, we print out the status of the above-mentioned attributes:

insert image description here

Use the setDaemon(Boolean value) method to set a thread as the background, true means the background thread.

class MyThread1 extends Thread{
    
    
    @Override
    public void run() {
    
    
        System.out.println("hello  t");
    }
}
public class Demo1 {
    
    
    public static void main(String[] args) {
    
    
        Thread t = new MyThread1();
        t.start();

        System.out.println("hello main");
        try {
    
    
            Thread.sleep(1000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        //设置为后台线程
        t.setDaemon(true);
        System.out.println("是否是后台线程 "+ t.isDaemon());
    }
}

Results of the:

insert image description here
The above-mentioned operations are obtained in a momentary state, not in a continuous state.

The difference between start() and run() methods:

When we call the start() method, a new thread is created (there is an action to create a thread to the system), and the thread will automatically call the run() method (entry method) by the system. And this run The () method is run in this newly created thread.
But if the programmer manually calls the run() method, a new thread will not be created, and the method is executed in the thread that called this method.

Get a reference to the current thread:

method illustrate
public static Thread currentThread(); Returns a reference to the current thread object
 public static void main(String[] args) {
    
    
 		//获取当前线程的引用
        Thread t = Thread.currentThread();
        //通过当前线程的引用调用当前线程的名字
        System.out.println("当前线程名字 : "+t.getName());
    }

Results of the:
insert image description here

Sleep the current thread :

method illustrate
public static void sleep(long millis) throws InterruptedException Sleeps the current thread for millis millis milliseconds
public static void sleep(long millis, int nanos) throwsInterruptedException Can sleep with higher precision
   public static void main(String[] args) {
    
    
        Thread t = new Thread(()->{
    
    
            System.out.println("hello t");
        });
        t.start();
        try {
    
    
            //睡眠1000ms,也可以称为阻塞1000ms
             Thread.sleep(1000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        System.out.println("hello main");
    }

The state of sleep is equivalent to the thread being blocked . The blocking time is determined by the parameters inside. The blocking time of this thread does not affect the execution of other threads. It can be understood that we are playing games, playing underage time The restriction pops up, and at this time we are required to stop playing the game, and only after the waiting time has passed can we continue to play the game.

Note : You can't do anything while waiting, it's equivalent to being fixed!!!

thread interrupt

Interrupting the thread is to let the thread finish executing the entry method (run method) as soon as possible. There are 2 methods.

(1) Directly manually create a flag to distinguish whether the thread is about to end.

public class ThreadDemo5 {
    
    
    static boolean flog = true;
    public static void main(String[] args)  {
    
    
        Thread t = new Thread(()->{
    
    
           while (flog){
    
    
               try {
    
    
                   Thread.sleep(500);
               } catch (InterruptedException e) {
    
    
                   e.printStackTrace();
               }
               System.out.println("线程运行中~~");
           }
            System.out.println("t 线程结束");
        });
        t.start();
        try {
    
    
            //睡眠3000ms
            Thread.sleep(3000);
            //将标志位设置为false终止上面的while()
            System.out.println("控制新线程结束");
            flog = false;
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
    }
}

operation result:

insert image description here
Some threads may have some loops that need to be executed, but they may only need to be executed for a certain period of time, not all the time, so sleep() can be used to control the end time of this thread.

It should be noted that: flog needs to be a member variable, local variables are private to threads, and other threads cannot be modified, but member variables are in the data area of ​​the process and are shared resources, so they can be accessed and modified~~

Thread has built-in flags, and there is no need to manually create flags.

(2) Thread built-in flag

public class ThreadDemo5 {
    
    
    static boolean flog = true;
    public static void main(String[] args)  {
    
    
        Thread t = new Thread(()->{
    
    
           while (!Thread.currentThread().isInterrupted()){
    
    
               try {
    
    
                   Thread.sleep(500);
               } catch (InterruptedException e) {
    
    
                   e.printStackTrace();
               }
               System.out.println("线程运行中~~");
           }
            System.out.println("t 线程结束");
        });
        t.start();
        try {
    
    
            //睡眠3000ms
            Thread.sleep(3000);
            //将标志位设置为false终止上面的while()
            System.out.println("控制新线程结束");
           t.interrupt();
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
    }
}

insert image description here
Thread.currentThread(). This is a static method of the Thread class, through which the current thread can be obtained, similar to this;

The isInterrupted() method is a built-in flag for judging. The default is false, and true means that the thread will be interrupted . Run it now to see the result.

insert image description here

Why does the thread continue to execute after an exception is thrown?

That's because when the code executes to interrupt(), it does two things:

(1) If the t thread is not in the blocked state, then interrupt() will modify the built-in flag and set the state of isInterrupted to true;

(2) If the t thread is in the blocked state, interrupt()it will wake up the blocked state (sleep) in advance by triggering an exception at this time, but the flag bit will become false because the sleep wakes up, that is, the flag bit will be cleared, if the flag bit If it is false, it remains unchanged. Since our loop condition is while(!Thread.currentThread().isInterrupted()), and because our flag bit has become false again, we can continue to execute this loop.

There are many ways to cause blocking in practice, not only sleep, here is just an example of sleep.

Since the execution speed of the computer is very fast, the blocking state accounts for about 99.99% of the thread execution state, so there will be a greater chance of triggering (2).

Of course, even if it is blocked most of the time, the thread is always switching between the blocked state and the normal running state.

Of course, we can pass the break keyword. When an exception is thrown, we can stop executing the loop by breaking directly, and then we can end the thread. This is equivalent to my mother calling me to eat when I am playing a game. I dare not resist at this time , only to eat.

code show as below:

public class ThreadDemo5 {
    
    
    public static void main(String[] args)  {
    
    
        Thread t = new Thread(()->{
    
    
           while (!Thread.currentThread().isInterrupted()){
    
    
               try {
    
    
                   Thread.sleep(500);
               } catch (InterruptedException e) {
    
    
                   e.printStackTrace();
                    break;
               }
               System.out.println("线程运行中~~");
           }
            System.out.println("t 线程结束");
        });
        t.start();
        try {
    
    
            //睡眠3000ms
            Thread.sleep(3000);
            //将标志位设置为false终止上面的while()
            System.out.println("控制新线程结束");
           t.interrupt();
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
    }
}

The result of running at this time:

insert image description here
Of course, since we caught the exception, we can not only let him break directly, but also let him wait for a while before ending the execution.

as if we were calling:

For example, I am playing a game, and my girlfriend asks me to go out to buy groceries. At this time, I ignore her. At this time, it is equivalent to saying what you say is yours and I will do mine.

But what? After a while, my girlfriend came to me again and asked me to go grocery shopping. I was afraid that she would get angry, so I told her, five minutes, five minutes... I will quit when the five minutes are up. The game went grocery shopping.

When I finished buying groceries, I just lay down on the bed and turned on the game, and my girlfriend screamed from the kitchen, so I had to put down my phone immediately to see what happened...

Summarize the three states; (1) exit immediately (2) wait for a while before exiting (3) do not exit, you say yours and I will do mine.

It is up to us to decide when to quit.

If it is written directly to death, I have to quit when I receive an order. If I am reporting to my boss and my girlfriend asks me to go grocery shopping, if I hang up the boss's phone, then I will send it myself.

Only you have the right to decide what you want to do, other people's words can be regarded as opinions, only you are for your own good.

wait for a thread

Thread is a random scheduling process, waiting for thread is to control the end order of two threads.

But what? We can join()control the execution order of threads through methods.

Let's look at the following code and execution results:

insert image description here
Since threads are executed preemptively, main may be printed first this time, but t may be printed first next time, but programmers don't like this kind of uncertainty, so we can control the order through methods join().

Let's look at the following code and execution results:

insert image description here
When we call in the main thread t.join(), the content in the main thread will be executed only after the t thread is executed. We can also understand that in which thread the join()method is called, which thread is blocked, only when the call After the thread corresponding to the reference of this method is executed, the subsequent code can be executed~

insert image description here
Of course, this join()can also pass parameters. If the t thread has not been executed, then my thread will not work? Still have to wait for a lifetime? So at this time we can pass a parameter as the maximum waiting time. After this time, I won’t wait anymore. There are so many beauties in the world, can’t I just lick it with someone else?

The join method itself will also block, and any blocked method of the Java thread may throw this exception ( throws InterruptedException).

join has two behaviors:

(1) If the waiting thread has not finished executing, then block the waiting directly;

For example: I pick up my child from school, he leaves school at 5.00, and I arrive at 4.50, at this time I need to wait for him to leave school before I can go home.

(2) If the waiting thread has finished executing, it returns directly.

For example: I pick up my child from school, he leaves school at 5.00, and I arrive at 5.10, then I don't have to wait, I can pick it up directly.

When the join method does not take parameters, it just waits and waits forever. When the method takes parameters, if the maximum waiting time is exceeded, the code of the next step will be executed. Generally write the join method with parameters.

Guess you like

Origin blog.csdn.net/xiaoyubuhuiqiche/article/details/129655077