线程状态
Java中线程的状态分为6种。
- 初始(NEW):新创建一个线程对象,但还没有调用start()方法。
- 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被CPU调度,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。 - 阻塞(BLOCKED):表示线程阻塞于锁。
- 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
- 超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
- 终止(TERMINATED):表示该线程已经执行完毕。
线程状态及状态装换如下图所示
线程常用方法
1、sleep():让出CPU,拥有锁不释放锁(TImedWaiting),可在任意地方调用,不必非得在同步代码中 可以使调用线程睡眠相应的时间,睡足时间后便又回到可运行状态等待CPU调度。
2、yield():** netive静态方法,让出CPU,拥有锁不释放锁,并回到可运行状态(Ready),和其他可运行线程一起等待CPU调度**,可能CPU依旧会调用到该线程。
3、join():使当前线程进入等待状态(Waiting),等待调用线程执行完后才能继续运行,join(time):使得线程在预计时间后和当前线程并行执行(TimeWaiting)
4、wait(): 将当前线程锁释放并进入等待状态(Waiting),wait(time)进入等待状态(TimeWaiting),在等待时间内未被唤醒则自动醒来,防止永久等待,必须在同步方法中调用
5、notify() / notifyAll():唤醒某个(无法确定是哪个线程) / 所有等待中的线程当前线程不释放锁。
6、interrupt():打断某个线程(设置中断标志为true),但是不能打断正在竞争锁的线程,如果对调用sleep()、wait()、join()的线程设置标志位会抛异常InterruptedException,必须进行捕获处理。
7、如果想打断线程争抢锁(设置标志位),那么使用ReentrantLock,用锁对象调用lockInterruptibly(),如果有设置标志位则抛异常(InterruptedException)
8、isInterrupted():查询某线程是不是被打断过
9、interrupted():静态方法,当前线程是不是被打断过,如果打断过,并恢复打断标志位false
10、stop():直接暂停线程,释放所有锁,容易产生数据不一致问题,不建议使用(已过时方法)
11、suspend()、resume():暂停线程与恢复线程,容易产生数据不一致问题,不建议使用(已过时方法)
优雅的结束某线程
1、结合interrupt()与( isInterrupted()或interrupted() )方法:达到某条件便设置打断标志位,检查标志位为true结束。(不依赖线程中间状态,针对wait(),sleep()等抛出异常的情况在catch语句块中也可做标志位的检查)
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
while(true){
System.out.println("Thread is interrupted ! ");
System.out.println(Thread.currentThread().isInterrupted());
if (Thread.currentThread().isInterrupted()) {
break;
}
/*if (Thread.interrupted()) {
break;
}*/
}
});
t.start();
Thread.sleep(2000L);
t.interrupt();
}
}
2、使用Volatile实现优雅结束线程(不依赖于线程的中间状态,Volatile没有啥问题),这里的中间状态比如说:线程中执行装数据,必须装到好多个数据就暂停。但是针对wait()、sleep()等抛异常的情况无法校验running标志。
public class ThreadTest {
private static volatile boolean running = true;
private static void m() {
System.out.println("m start");
while (running) {
System.out.println("hello");
}
System.out.println("m end!");
}
public static void main(String[] args) throws InterruptedException {
new Thread(Tets::m, "t1").start();
Thread.sleep(1000L);
running = false;
}
}