Level 1: Thread status and scheduling
related information
Thread state and scheduling
If you understand the picture below, your understanding of threads will be improved.
-
When we use
new
keywords to create a new thread, the thread enters the newly created state (New
), which is the unstarted state in the figure; -
Call
start
the method to start the thread, and at this time it enters the runnable state, that is, the ready state (Runnable
); -
The ready state acquires CPU resources, starts to execute
run
the method, and enters the running state (Running
); -
Blocked state (
Blocked
): The blocked state means that the thread gives up the right to use the CPU for some reason and temporarily stops running. Until the thread enters the ready state, it has the opportunity to go to the running state. There are three types of blocking:-
Waiting for blocking: The running thread executes
wait()
the method, and the JVM will put the thread into the waiting pool. (wait
will release the lock held); -
Synchronous blocking: When the running thread acquires the synchronization lock of the object, if the synchronization lock is occupied by other threads, the JVM will put the thread into the lock pool;
-
Other blocking: When a running thread executes a method
sleep()
orjoin()
an I/O request is issued, the JVM will put the thread in a blocked state. Whensleep()
the state times out,join()
the waiting thread terminates or times out, or the I/O processing is completed, the thread re-transfers to the ready state. (Note thatsleep
the held lock will not be released);
-
-
Dead state ( ): The thread ends its life cycle
Dead
when the thread finishes executing or exits the method due to an exception .run()
thread priority
We know that the execution of multiple threads is random, and which thread is executed in a certain period of time depends on which thread has the CPU
execution permission at this time.
In Java
the medium thread has priority, and the thread with high priority will get more running opportunities.
Java
The priority of the thread is represented by an integer, and the value range is 1~10
. Thread
The class has the following three static constants:
static int MAX_PRIORITY
线程可以具有的最高优先级,取值为10。
static int MIN_PRIORITY
线程可以具有的最低优先级,取值为1。
static int NORM_PRIORITY
分配给线程的默认优先级,取值为5。
If you want to set and get the thread's priority, you can use Thread
the class's setPriority()
and getPriority()
methods.
Each thread has a default priority. The default priority of the main thread is Thread.NORM_PRIORITY
.
The priority of a thread has an inheritance relationship. For example, if a thread A
is created in a thread B
, B
it will A
have the same priority as the thread.
The JVM provides 10
several thread priorities, but none of them map well with common operating systems. If you want the program to be ported to various operating systems, you should only use Thread
the following three static constants as priorities, so as to ensure that the same priority uses the same scheduling method.
You also need to know about thread scheduling and priority:
-
ThreadSleep :
Thread.sleep(long millis)
Method that makes a thread go to a blocked state.millis
The parameter sets the time to sleep, in milliseconds. When the sleep is over, it turns to the ready (Runnable
) state.sleep()
Platform portability is good. -
Thread wait : A method
Object
in a classwait()
that causes the current thread to wait until other threads call the object'snotify()
method ornotifyAll()
wakeup method. These two wake-up methods are alsoObject
methods in the class, and the behavior is equivalent to callingwait(0)
. -
Thread concession :
Thread.yield()
method, suspend the currently executing thread object, and give the execution opportunity to the same or higher priority thread. -
ThreadJoin :
join()
method, waits for other threads to terminate. If the method of another thread is called in the current threadjoin()
, the current thread will enter the blocking state until the other process finishes running, and then the current thread will change from blocking to ready state. -
thread wakeup : method
Object
in the classnotify()
that wakes up a single thread waiting on this object's monitor. If all threads are waiting on this object, one of the threads will be chosen to wake up. The choice is arbitrary and occurs when the decision on the implementation is made. A thread waits on an object's monitor by calling one of itswait
methods . The awakened thread cannot continue executing until the current thread relinquishes the lock on this object. The awakened thread will compete in the usual way with all other threads actively synchronizing on this object; for example, the awakened thread has no reliable privilege or disadvantage in being the next thread to lock on this object. There is another similar methodnotifyAll()
, which wakes up all threads waiting on this object monitor.
programming requirements
slightly.
Level 2: Common functions (1)
related information
sleep() function
sleep(long millis)
: Sleeps (pauses execution) the currently executing thread for the specified number of milliseconds.
The way of use is very simple and can be used inside the thread Thread.sleep(millis)
.
sleep()
Make the current thread enter a stagnant state (block the current thread) and give up the use of the CPU. The purpose is to prevent the current thread from occupying the CPU resources obtained by the process alone, so as to leave a certain period of time for other threads to execute;
The thread does not necessarily execute immediately after sleep()
the sleep time expires, because other threads may be running and not scheduled to give up execution, unless this thread has a higher priority.
join() function
join
The definition of the function means: wait for the thread to terminate .
When we run the thread, we may encounter the situation that when the sub-thread is run in the main thread, the main thread needs to obtain the final execution result of the sub-thread.
But in many cases, the sub-threads perform a lot of time-consuming operations, and the main thread often ends before the sub-threads. At this time, the main thread cannot obtain the final execution results of the sub-threads.
Use join
functions to solve this problem.
Let's understand with two examples:
Version without join
function:
class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
public void run() {
System.out.println("子线程开始运行");
for (int i = 0; i < 5; i++) {
System.out.println("子线程" + name + "运行" + i);
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackT\frace();
}
}
System.out.println("子线程结束");
}
}
public class Test {
public static void main(String[] args) {
Thread t = new MyThread("子线程A");
t.start();
for (int i = 0; i < 5; i++) {
System.out.println("主线程执行" + i);
}
System.out.println("主线程结束");
}
}
/**************************/
输出结果(每次都不一样):
主线程执行0
主线程执行1
主线程执行2
主线程执行3
主线程执行4
主线程结束
子线程开始运行
子线程子线程A运行0
子线程子线程A运行1
子线程子线程A运行2
子线程子线程A运行3
子线程子线程A运行4
子线程结束
It can be found that every time it runs, the main thread ends before the child thread.
Use join
function:
package step1;
class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
public void run() {
System.out.println("子线程开始运行");
for (int i = 0; i < 5; i++) {
System.out.println("子线程" + name + "运行" + i);
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackT\frace();
}
}
System.out.println("子线程结束");
}
}
public class Test {
public static void main(String[] args) {
Thread t = new MyThread("子线程A");
t.start();
for (int i = 0; i < 5; i++) {
System.out.println("主线程执行" + i);
}
try {
t.join();
} catch (Exception e) {
e.printStackT\frace();
}
System.out.println("主线程结束");
}
}
/****************************************************/
输出结果:
主线程执行0
主线程执行1
主线程执行2
主线程执行3
子线程开始运行
主线程执行4
子线程子线程A运行0
子线程子线程A运行1
子线程子线程A运行2
子线程子线程A运行3
子线程子线程A运行4
子线程结束
主线程结束
It can be found that no matter how many times it runs, the main thread will wait for the child thread to end before ending.
programming requirements
Begin - End
Please read the code on the right carefully, and supplement the code in the area according to the prompts in the method . The specific tasks are as follows:
- Create a custom thread to realize
num
the value of the first Fibonacci sequencenum
from0
the beginning, andmain
obtain the final calculation result of the sub-thread in the function.
package step2;
import java.util.Scanner;
public class Task {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
//请在此添加实现代码
/********** Begin **********/
Thread t=new MyThread("子线程",num);
t.start();
/********** End **********/
}
}
//请在此添加实现代码
/********** Begin **********/
class MyThread extends Thread {
private String name;
private int num;
public MyThread(String n,int m){
this.name=n;
this.num=m;
}
public void run(){
int a=1;
int b=1;
if(num==1|num==2){
System.out.println("子线程计算结果为:"+b);
}
for(int i=0;i<num-2;i++){
int t=a;
a=b;
b=t+a;
}
System.out.println("子线程计算结果为:"+b);
}
}
/********** End **********/
Level 3: Common Functions (2)
related information
yield function
yield
Function can be understood as "concession", its role is: suspend the currently executing thread object, and execute other threads.
yield()
What should be done is to return the currently running thread to a runnable state to allow other threads of the same priority to get a chance to run. Therefore, the purpose of use yield()的
is to allow appropriate round-robin execution between threads of the same priority . However, in practice, there is no guarantee yield()
that the purpose of yielding will be achieved, because the yielding thread may be selected again by the thread scheduler.
Example:
public class Task {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+"主线程运行开始!");
MyThread mTh1=new MyThread("A");
MyThread mTh2=new MyThread("B");
mTh1.start();
mTh2.start();
System.out.println(Thread.currentThread().getName()+ "主线程运行结束!");
}
}
class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println(name + "线程" + "执行" + i);
if(i == 10){
this.yield();
}
}
}
}
/************************************************************************/
运行结果有两种情况:
第一种情况:A(线程)当执行到10时会让掉CPU时间,这时B(线程)抢到CPU时间并执行。
第二种情况:B(线程)当执行到10时会让掉CPU时间,这时A(线程)抢到CPU时间并执行。
We can also consider adding setPriority
a function to change the priority of the thread to change the execution order of the thread.
wait function
To understand wait
functions we first need to understand the concept of thread locks . Thread lock: In fact, it is like the lock in our daily life. If a house is locked, others cannot get in. It is similar in Java. If a piece of code acquires a lock, then other places cannot run this code. Can wait for the lock to be released.
Here we will involve two functions, 1. wait()
, 2. notify()
. These two functions are Object
functions that come with the class.
In the following example, we will use it synchronized(Obj)
to achieve thread synchronization. The concept of synchronization will be mentioned later. It doesn't matter if you don't understand it here, and it will not affect your wait
understanding of functions.
Functionally speaking:
-
wait()
That is to say, after the thread acquires the object lock, it actively releases the object lock, and the thread sleeps at the same time. Until another thread calls the object tonotify()
wake up the thread, it can continue to acquire the object lock and continue to execute; -
The corresponding
notify()
is the wake-up operation of the object lock.
But one thing to note is that after the call, the object lock is not released immediately, but after the execution of the notify()
corresponding statement block is completed, after the lock is automatically released, the JVM will randomly select a thread from the object-locked threads and give it the object lock. lock, wake up the thread, and continue execution. This provides synchronization and wake-up operations between threads.synchronized(){}
wait()
Thread.sleep()
Both Object.wait()
of them can suspend the current thread and release the control of the CPU. The main difference is that Object.wait()
the control of the object lock is released at the same time as the CPU is released.
What is learned on paper is superficial. If you want to know this, you have to do it yourself. We still learn the usage of these functions through examples.
Question: Create two threads, A thread prints 5
times A
, B thread prints 5
times B
, the threads are required to run at the same time, and print 5
times alternately AB
.
This problem can be Object
solved easily. code show as below:wait()
notify()
public class MyThread implements Runnable {
private String name;
private Object prev;
private Object self;
private MyThread(String name, Object prev, Object self) {
this.name = name;
this.prev = prev;
this.self = self;
}
public void run() {
int count = 5;
while (count > 0) {
synchronized (prev) {
synchronized (self) {
System.out.print(name);
count--;
self.notify();
}
try {
prev.wait();
} catch (InterruptedException e) {
e.printStackT\frace();
}
}
}
System.exit(0);//退出jvm
}
public static void main(String[] args) throws Exception {
Object a = new Object();
Object b = new Object();
MyThread ta = new MyThread("A", b, a);
MyThread tb = new MyThread("B", a, b);
new Thread(ta).start();
Thread.sleep(100); //确保按顺序A、B执行
new Thread(tb).start();
Thread.sleep(100);
}
}
/********************************************************************/
运行程序,结果为:
ABABABABAB
Summary of common thread functions
The following table lists the commonly used functions of the thread class:
function | describe |
---|---|
public void start() | Causes the thread to begin executing; the Java virtual machine calls the thread's run method. |
public void run() | If the thread was constructed using an independent Runnable run object, the Runnable object's run method is invoked; otherwise, the method does nothing and returns. |
public final void setName(String name) | Change the thread name to be the same as the parameter name. |
public final void setPriority(int priority) | Change the priority of a thread. |
public final void setDaemon(boolean on) | Mark the thread as a daemon or user thread. |
public final void join(long millisec) | The maximum time to wait for this thread to terminate is millis milliseconds |
public void interrupt() | Interrupt thread. |
public final boolean isAlive() | Tests whether the thread is alive. |
public static void yield() | Suspends the currently executing thread object and executes other threads. |
public static void sleep(long millisec) | Sleeps (pauses execution) the currently executing thread for the specified number of milliseconds, subject to the precision and accuracy of system timers and the scheduler. |
public static boolean holdsLock(Object x) | Returns true if and only if the current thread holds the monitor lock on the specified object. |
public static Thread currentThread() | Returns a reference to the currently executing thread object. |
public static void dumpStack() | Print the current thread's stack trace to the standard error stream. |
programming requirements
Begin - End
Please read the code on the right carefully, and supplement the code in the area according to the prompts in the method . The specific tasks are as follows:
- Create three threads,
A
thread print5
timesE
, thread B print5
timesD
,C
thread print5
timesU
, require threads to run at the same time, print5
times alternatelyEDU
.
package step3;
public class MyThread implements Runnable {
//请在此添加实现代码
/********** Begin **********/
private String name;
private Object prev;
private Object self;
private MyThread(String name,Object prev,Object self){
this.name = name;
this.prev = prev;
this.self = self;
}
public void run(){
int count = 5;
while(count>0){
synchronized(prev){
synchronized(self){
System.out.print(name);
count--;
self.notify();
}
try {
prev.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.exit(0);
}
public static void main(String[] args) throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();
MyThread ta = new MyThread("E",c,a);
MyThread tb = new MyThread("D",a,b);
MyThread tc = new MyThread("U",b,c);
new Thread(ta).start();
Thread.sleep(10);
new Thread(tb).start();
Thread.sleep(10);
new Thread(tc).start();
Thread.sleep(10);
}
/********** End **********/
}