线程的生命周期
1.生命周期
一个线程从创建,到最终的消亡,需要经历多种不同的状态,而这些不同的线程状态,由始至终也构成了线程生命周期的不同阶段。线程的生命周期可以总结为下图。
其中,几个重要的状态如下所示。
- NEW:初始状态,线程被构建,调用new Thread(),但是还没有调用start()方法。
- RUNNABLE:可运行状态,可运行状态可以包括:运行中状态和就绪状态,就绪状态是调用了start()方法,但是没有获取CPU资源,等待获取CPU资源的状态,一旦获取了CPU资源线程调度器开始调度就会开始执行run()方法这时候就会变为运行中状态。
- BLOCKED:阻塞状态,需要获取synchronized锁,但是没有获取到,被别的线程获取到,就会处于阻塞状态。处于这个状态的线程需要等待其他线程释放锁或者等待进入synchronized。
- WAITING:表示等待状态,当前正在运行的线程调用object.wait()Thread.join(),LockSuppore.park()就会进入waiting等待状态,处于该状态的线程需要等待其他线程对其进行通知或中断等操作,进而进入下一个状态。
- TIME_WAITING:超时等待状态。可以在一定的时间自行返回。
- TERMINATED:终止状态,当前线程执行完毕。
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
/**
* title:${file_name}
* 关于线程状态的实验
*
* @version 2.0
* @date ${date}
*/
public class T04_ThreadState {
public static void main(String[] args) throws Exception {
//===================================================
Thread t1 = new Thread(() -> {
System.out.println("2: " + Thread.currentThread().getState());//RUNNABLE
for (int i = 0; i < 3; i++) {
SleepHelper.sleepSeconds(1);
System.out.print(i + " ");//0 1 2
}
System.out.println();//run执行结束标志t1线程执行结束
});
System.out.println("1: " + t1.getState());// NEW
t1.start();
t1.join();//阻塞主线程,T1线程先执行run方法,T1执行完毕再执行后面的
System.out.println("3: " + t1.getState());//TERMINATED 终止
//===================================================
Thread t2 = new Thread(() -> {
try {
LockSupport.park();//让t2自己阻塞
System.out.println("t2 go on!");
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t2.start();//运行t2开始 准备被调度执行
TimeUnit.SECONDS.sleep(1);//主线程休眠 t2肯定会执行
System.out.println("4: " + t2.getState());//LockSupport.park();让t2等待变为waiting状态
LockSupport.unpark(t2);//唤醒T2 t2继续执行run方法LockSupport.park()后的内容 输出t2 go on! 然后t2休眠5秒
TimeUnit.SECONDS.sleep(1);//主线程休眠
System.out.println("5: " + t2.getState());//t2唤醒之后又调用sleep(5)方法 ,指定时间5秒, 所以会timed waiting
//===================================================
final Object o = new Object();
Thread t3 = new Thread(() -> {
synchronized (o) {
System.out.println("t3 getLock o");
}
});//只是new t3线程此时是new状态 没调用start方法,不会等待执行
new Thread(() -> {
synchronized (o) {
System.out.println("wait 5s start");
SleepHelper.sleepSeconds(5);
System.out.println("wait 5s end");
}
}).start();//调用start方法,准备调度获得执行机会
SleepHelper.sleepSeconds(1);//主线程休眠1秒 上面new Thread会执行,竞争成功,获取synchronized关键字 输出wait 5s start
// 然后休眠5秒 输出wait 5s end 释放抢占资源 T3运行start方法之后才有机会获取synchronized关键字 执行方法 输出t3 getLock o
t3.start();
SleepHelper.sleepSeconds(1);//主线程休眠1秒
System.out.println("6: " + t3.getState());//此时还在等待System.out.println("wait 5s start");
//SleepHelper.sleepSeconds(5); 这个5秒走完获取synchronized关键字 此时是BLOCKED状态 等待获取synchronized
//===================================================
final Lock lock = new ReentrantLock();
Thread t4 = new Thread(() -> {
lock.lock(); //省略try finally
System.out.println("t4 getLock o");
lock.unlock();
});
new Thread(() -> {
lock.lock();
SleepHelper.sleepSeconds(5);
lock.unlock();
}).start();
SleepHelper.sleepSeconds(1);//主线程休眠 上面线程调度执行 等待5秒释放lock锁
t4.start();
SleepHelper.sleepSeconds(1);//主线程休眠 t4等待上面线程释放lock锁 等待执行
System.out.println("7: " + t4.getState());//等待获取lock,所以是WAITING
//===================================================
Thread t5 = new Thread(() -> {
LockSupport.park();
});
t5.start();
SleepHelper.sleepSeconds(1);//t5执行 LockSupport.park()阻塞自己线程
System.out.println("8: " + t5.getState()); //WAITING状态
LockSupport.unpark(t5);//释放
}
}
//yield 让出去一下,等待线程调度器再次随机调度 还可能调到自己
1: NEW
2: RUNNABLE
0 1 2
3: TERMINATED
4: WAITING
t2 go on!
5: TIMED_WAITING
wait 5s start
6: BLOCKED
7: WAITING
wait 5s end
t3 getLock o
8: WAITING
t4 getLock o
2.线程的“打断”
• interrupt()
打断某个线程(设置标志位)
• isInterrupted()
查询某线程是否被打断过(查询标志位)
• static interrupted()
查询当前线程是否被打断过,并重置打断标志
isInterrupted()和interrupt()
/**
* interrupt()与isInterrupted()
* 设置标志位 + 查询标志位
* • interrupt()
* • 打断某个线程(设置标志位)
* • isInterrupted()
* • 查询某线程是否被打断过(查询标志位)
* • static interrupted()
* • 查询当前线程是否被打断过,并重置打断标志
*/
public class T05_Interrupt_and_isInterrupted {
public static void main(String[] args) {
Thread t = new Thread(() -> {
for (; ; ) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("Thread is interrupted!");
System.out.println(Thread.currentThread().isInterrupted());
break;
}
}
});
t.start();
SleepHelper.sleepSeconds(2);
t.interrupt();
}
}
/*
* 先new一个Thread对象
* t.start(); 线程准备启动,等待CPU给资源
* SleepHelper.sleepSeconds(2); 主线程阻塞 这时候t运行 因为
* Thread.currentThread().isInterrupted()查询是否设置标志位,如果没有设置不执行if
* 等主线程sleep结束,等获取到资源开始运行 当执行 t.interrupt(); 设置标志位 这时候t线程开始
* 进入if里边的代码块 输出 Thread is interrupted! true
* break跳出for循环 程序结束
*
* */
输出结果:
Thread is interrupted!
true
interrupted()和interrupt()
interrupted 查询当前线程是否被打断过,并重置打断标志
/**
* interrupt与interrupted()
* • interrupt()
* • 打断某个线程(设置标志位)
* • isInterrupted()
* • 查询某线程是否被打断过(查询标志位)
* • static interrupted()
* • 查询当前线程是否被打断过,并重置打断标志
*/
public class T06_Interrupt_and_interrupted {
public static void main(String[] args) {
Thread t = new Thread(() -> {
for (; ; ) {
if (Thread.interrupted()) {//查询当前线程是否被打断过,并重置打断标志
System.out.println("Thread is interrupted!");
System.out.println(Thread.interrupted());//查询当前线程是否被打断过,并重置打断标志
}
}
});
t.start();
SleepHelper.sleepSeconds(2);
t.interrupt();//打断某个线程(设置标志位)
// Thread.currentThread().interrupt();
//思考一下,如果在这里写
System.out.println("main: " + t.interrupted());//查询当前线程是否被打断过,并重置打断标志
// 所以这里输出的是当前main线程 因为main线程没有调用设置标志位 所以输出false 如果输出前面调用Thread.currentThread().interrupt();设置标志位 那么这里就输出true
//输出的是哪个线程的中断状态
}
}
Thread is interrupted!
false
main: true
Interrupt_and_sleep
interrupt与sleep() wait() join() 可以设置标志位 会抛出异常 可以catch异常 catch异常之后标志位会复位 主动权给线程本身
/**
* interrupt与sleep() wait() join() 可以设置标志位 会抛出异常 可以catch异常 catch异常之后标志位会复位 主动权给线程本身
*/
public class T07_Interrupt_and_sleep {
public static void main(String[] args) {
Thread t = new Thread(() -> {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {//捕获异常 标志位复位
System.out.println("Thread is interrupted!");
System.out.println(Thread.currentThread().isInterrupted());
}
});
t.start();
SleepHelper.sleepSeconds(5);
t.interrupt();//调用这个方法会打断t线程内的sleep方法 提前结束休眠
}
}
Thread is interrupted!
false
Interrupt_and_wait
interrupt与sleep() wait() join() 可以设置标志位 会抛出异常 可以catch异常 catch异常之后标志位会复位 主动权给线程本身
/**
* interrupt与sleep() wait() join()
*/
public class T08_Interrupt_and_wait {
private static Object o = new Object();
public static void main(String[] args) {
Thread t = new Thread(() -> {
synchronized (o) {
try {
o.wait();
} catch (InterruptedException e) {
System.out.println("Thread is interrupted!");
System.out.println(Thread.currentThread().isInterrupted());
}
}
});
t.start();
SleepHelper.sleepSeconds(5);
t.interrupt();//打断t线程的wait等待
}
}
Thread is interrupted!
false
Interrupt_and_sync
设置标志位 不会中断抢锁过程 线程之间锁的竞争不会受标志位中断的影响
/**
* interrupt与sleep() wait() join()
*/
public class T09_Interrupt_and_sync {
private static Object o = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized (o) {
SleepHelper.sleepSeconds(10);
}
});
t1.start();
SleepHelper.sleepSeconds(1);
Thread t2 = new Thread(() -> {
synchronized (o) {
}
System.out.println("t2 end!");
});
t2.start();
SleepHelper.sleepSeconds(1);
t2.interrupt();//t2在等t1休眠10秒释放锁 即使这个时候对t2标志位进行修改 也不会中断干扰抢锁过程
}
}
//设置标志位 不会中断抢锁过程
t2 end!
Interrupt_and_lock
设置标志位 不会中断抢lock锁过程
import java.util.concurrent.locks.ReentrantLock;
/**
* interrupt与sleep() wait() join()
*/
public class T10_Interrupt_and_lock {
private static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
lock.lock();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
System.out.println("t1 end!");
});
t1.start();
SleepHelper.sleepSeconds(1);
Thread t2 = new Thread(() -> {
lock.lock();
try {
} finally {
lock.unlock();
}
System.out.println("t2 end!");
});
t2.start();
SleepHelper.sleepSeconds(1);
t2.interrupt();//不会中断t2的获取ReentrantLock锁状态
}
}
t1 end!
t2 end!
Interrupt_and_lockInterruptibly
import java.util.concurrent.locks.ReentrantLock;
/**
* interrupt与lockInterruptibly()
*/
public class T11_Interrupt_and_lockInterruptibly {
private static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
lock.lock();
try {
SleepHelper.sleepSeconds(10);
} finally {
lock.unlock();
}
System.out.println("t1 end!");
});
t1.start();
SleepHelper.sleepSeconds(1);
Thread t2 = new Thread(() -> {
System.out.println("t2 start!");
try {
lock.lockInterruptibly();//可以被打断的过程 抢锁过程中如果该线程的标志位被改变会抛出异常
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
System.out.println("t2 end!");
});
t2.start();
SleepHelper.sleepSeconds(1);
t2.interrupt();//会中断t2的lock.lockInterruptibly(); 直接进入catch块捕获异常 执行finally 不执行别的
}
}
t2 start!
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
at com.mashibing.juc.c_000_threadbasic.T11_Interrupt_and_lockInterruptibly.lambda$main 1 ( T 1 1 I n t e r r u p t a n d l o c k I n t e r r u p t i b l y . j a v a : 33 ) a t j a v a . l a n g . T h r e a d . r u n ( T h r e a d . j a v a : 748 ) E x c e p t i o n i n t h r e a d " T h r e a d − 1 " j a v a . l a n g . I l l e g a l M o n i t o r S t a t e E x c e p t i o n a t j a v a . u t i l . c o n c u r r e n t . l o c k s . R e e n t r a n t L o c k 1(T11_Interrupt_and_lockInterruptibly.java:33) at java.lang.Thread.run(Thread.java:748) Exception in thread "Thread-1" java.lang.IllegalMonitorStateException at java.util.concurrent.locks.ReentrantLock 1(T11InterruptandlockInterruptibly.java:33)atjava.lang.Thread.run(Thread.java:748)Exceptioninthread"Thread−1"java.lang.IllegalMonitorStateExceptionatjava.util.concurrent.locks.ReentrantLockSync.tryRelease(ReentrantLock.java:151)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
at com.mashibing.juc.c_000_threadbasic.T11_Interrupt_and_lockInterruptibly.lambda$main$1(T11_Interrupt_and_lockInterruptibly.java:37)
at java.lang.Thread.run(Thread.java:748)
t1 end!
LockSupport_interrupt
public class T05_InterruptAndPark {
public static void main(String[] args) {
Thread t = new Thread(() -> {
System.out.println("1");
LockSupport.park();
System.out.println("2");
});
t.start();
SleepHelper.sleepSeconds(5);
t.interrupt();//打断park
}
}
总结:
- t.interrupt();//调用这个方法会打断t线程内的sleep方法 提前结束休眠;
- t.interrupt();//打断t线程的wait等待;
- t2.interrupt();//synchronized:t2在等t1休眠10秒释放锁 即使这个时候对t2标志位进行修改 也不会中断干扰抢锁过程.
- t2.interrupt();//不会中断t2的获取ReentrantLock锁状态;
- t2.interrupt();//会中断t2的lock.lockInterruptibly(); 直接进入catch块捕获异常 执行finally 不执行别的。
- t.interrupt();//打断线程的LockSupport.park();