点进来你就是我的人了
博主主页:戳一戳,欢迎大佬指点!
目录
1.线程的状态
2. 线程的状态和转移
3.线程的状态演示
3.1 NEW (新建) 和 TERMINATED (终止)
3.2 RUNNABLE (可运行) 和TIME_WAITING (定时等待)
3.3 WAITING (等待)
3.4 BLOCKED (阻塞)
线程共有6种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。分别对应于:新建、可运行、阻塞、等待、定时等待、终止。
1)新建状态(NEW): 当我们创建一个新的Thread对象时,该线程就处于新建状态,例如:Thread t = new Thread();
2)可运行状态(RUNNABLE): 当线程对象调用start()方法后,线程进入可运行状态。在这个状态下,线程已经做好了准备,随时等待CPU调度执行,这个状态包括了"就绪"和"运行"状态。
3)阻塞状态(BLOCKED): 线程在等待获取一个锁以进入或重新进入同步代码块时,它会进入阻塞状态。只有当该锁被释放并且线程被调度去获取这个锁,线程才能转换到RUNNABLE状态。
4)等待状态(WAITING): 线程进入等待状态,是因为它调用了其它线程的join方法,或者调用了无参数的wait方法。在这种情况下,线程会等待另一个线程的操作完成或者等待notify/notifyAll消息。
5)定时等待状态(TIMED_WAITING): 线程进入定时等待状态,是因为它调用了sleep或者带有指定时间的wait或join方法。在指定的时间过去之后,线程会自动返回RUNNABLE状态。如果它是由于调用wait或join方法进入的定时等待状态,还需要等待notify/notifyAll消息或者等待join的线程终止。
6)终止状态(TERMINATED): 线程任务执行完毕或者由于异常而结束,线程就会进入终止状态。在这个状态下,线程的生命周期实际上已经结束了,它不能再转换到其他任何状态。
3.线程的状态演示
在这个程序之中,我们首先创建了一个Thread对象,然后运用lambda表达式来实现run方法.在run方法之中什么都不做,只是循环.然后打印在t.start之前和t线程运行完之后,线程所处的状态.其中t,join是为了让main线程等待t线程执行完毕后再继续执行,否则main方法可能会先执行完毕.
public class ThreadDemo1 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(()->{
for(int i = 0;i<1000000;i++){
}
});
//t调用start之前,是NEW状态.
System.out.println("线程执行之前:"+t.getState());
t.start();
t.join();
//线程执行完毕之后,就是TERMINATED状态.
System.out.println("线程执行之后:"+t.getState());
}
}
下面代码我们可以看见RUNNABLE,主要是因为我们当前线程的run方法里面没有sleep,join之类的方法,否则在后续打印中就不一定是RUNNABLE状态了.
public class ThreadDemo2 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(()->{
for(int i = 0;i<1000;i++){
}
});
System.out.println("线程执行之前:"+t.getState());
t.start();
//线程处于可执行状态
System.out.println("线程运行中:"+t.getState());
t.join();
System.out.println("线程运行完:"+t.getState());
}
}
我们使用wait方法可以使线程出现WAITING状态.在下面代码中,我们使t2线程等待t1线程,当t1线程执行完毕之后,t2线程才开始执行.
public class ThreadDemo3 {
public static void main(String[] args) throws InterruptedException {
Object obj = new Object();
Thread t1 = new Thread(()->{
for(int i = 0;i<1000;i++){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (obj){
obj.notify();
}
System.out.println("线程t1执行完毕!");
});
Thread t2 = new Thread(()->{
synchronized (obj){
try {
obj.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t1.start();
//此时t2没有调用start方法,是NEW
System.out.println("t2 start之前:"+t2.getState());
t2.start();
Thread.sleep(10);
//此时线程t2等待线程t1执行完毕,应该是WAITING状态
System.out.println("t2 wait中:"+t2.getState());
t1.join();
t2.join();
//此时t2执行完毕,TERMINATED
System.out.println("t2执行完成:"+t2.getState());
}
}
BLOCKED是阻塞状态,死锁就可能会出现这种状态.在下面代码中,我们创建了两个线程,一个t1,一个t2,我们先让t1获取obj1,然后再获取obj2.然后让t2获取obj2,再获取obj1.这样就可以构成死锁.因为,当t1获取到obj1的时候,t1获取到了obj1锁,t2获取到了obj2锁,他们获取完毕之后.然后他们想要获取对方的锁,此时就构成了死锁.也就出现了BLOCKED状态.
public class ThreadDemo4 {
public static void main(String[] args) throws InterruptedException {
Object obj1 = new Object();
Object obj2 = new Object();
Thread t1 = new Thread(()->{
synchronized (obj1){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (obj2){
}
}
});
Thread t2 = new Thread(()->{
synchronized (obj2){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (obj1){
}
}
});
t1.start();
Thread.sleep(100);
t2.start();
Thread.sleep(1500);
System.out.println(t2.getState());
t1.join();
t2.join();
}
}