线程状态的枚举:Thread.State
这 6 种状态被明确地定义在 Thread 类的一个内部枚举类 Thread.State 中:
NEW(新建) 一个尚未启动的线程处于这一状态。(线程new完)RUNNABLE(可运行) 一个正在 Java 虚拟机中执行的线程处于这一状态。(线程调用完start)BLOCKED(阻塞) 一个正在阻塞等待一个监视器锁的线程处于这一状态。(等待锁的状态)WAITING(等待) 一个正在无限期等待另一个线程执行一个特别的动作的线程处于这一状态。()动作指的是:这里所谓的动作通常即是指 “notify 或是 notifyAll”。TIMED_WAITING(计时等待) 一个正在限时等待另一个线程执行一个动作的线程处于这一状态。() 如果没有等到如 “notify” 之类的动作,时间到了也会自动退出这一状态。TERMINATED(终止) 一个已经退出的线程处于这一状态。()
wt.isInterrupted() 中断
sleep()和wait() 区别
sleep 方法和 wait 方法都是用来将线程进入休眠状态的,并且 sleep 和 wait 方法都可以响应 interrupt 中断,也就是线程在休眠的过程中,如果收到中断信号,都可以进行响应并中断,且都可以抛出 InterruptedException 异常
- wait 方法必须配合 synchronized 一起使用,不然在运行时就会抛出 IllegalMonitorStateException 的异常 =》而 sleep 可以单独使用,无需配合 synchronized 一起使用。
- 所属类不同:wait 方法属于 Object 类的方法,而 sleep 属于 Thread 类的方法
- 唤醒方式不同: sleep 方法具有主动唤醒功能,而不传递任何参数的 wait 方法只能被动的被唤醒。
- 释放锁资源不同:wait 方法会主动的释放锁,而 sleep 方法则不会。
- 线程进入状态不同:调用 sleep 方法线程会进入 TIMED_WAITING 有时限等待状态,而调用无参数的 wait 方法,线程会进入 WAITING 无时限等待状态。
在 Java 中,wait() 方法是 Object 类的一部分,用于线程间的通信和同步。它允许一个线程暂停执行,直到另一个线程通知它可以继续执行。以下是一个简单的示例,演示了如何使用 wait() 方法:
public class WaitExample {
private static final Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
synchronized (lock) {
System.out.println("Thread 1 is going to wait...");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 1 has been notified.");
}
});
Thread t2 = new Thread(() -> {
synchronized (lock) {
System.out.println("Thread 2 is going to notify...");
lock.notify();
System.out.println("Thread 2 has notified.");
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
在上面的示例中,我们定义了一个共享的锁对象 lock,然后创建了两个线程 t1 和 t2。线程 t1 在获取锁后调用 wait() 方法,进入等待状态,直到被其他线程通知。线程 t2 在获取锁后调用 notify() 方法,通知等待的线程 t1 可以继续执行。
输出结果可能类似于:
Thread 1 is going to wait...
Thread 2 is going to notify...
Thread 2 has notified.
Thread 1 has been notified.
请注意,在使用 wait() 和 notify() 方法时,必须在同步块或方法中调用,否则会抛出 IllegalMonitorStateException 异常。同时,使用 wait() 方法的线程可能会被中断,需要捕获 InterruptedException 异常。
Thread.join()方法
join()方法是Thread类的一个实例方法。它的作用是让当前线程陷入“等待”状态,等join的这个线程执行完成后,再继续执行当前线程。
有时候,主线程创建并启动了子线程,如果子线程中需要进行大量的耗时运算,主线程往往将早于子线程结束之前结束。
如果主线程想等待子线程执行完毕后,获得子线程中的处理完的某个数据,就要用到join方法了。
示例代码:
public class Join {
static class ThreadA implements Runnable {
@Override
public void run() {
try {
System.out.println("我是子线程,我先睡一秒");
Thread.sleep(1000);
System.out.println("我是子线程,我睡完了一秒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new ThreadA());
thread.start();
thread.join();
System.out.println("如果不加join方法,我会先被打出来,加了就不一样了");
}
}
线程中断是什么机制呢?
java.lang.Thread#interrupt()方法是实例级方法。当线程正在执行wait()、sleep()、join()方法时线程是处于【waitting】状态,可理解为内部仍会不断地检查中断状态(interrupt status)的值;interrupt方法会改变目标线程的中断状态(interrupt status);所以当被interrupt()后,则抛出InterruptedException异常。
还有一个重点:异常抛出后,线程内的中断状态会被重置为false,所以如果捕获到异常,之后要安排好退出线程的逻辑,否则就可能是bug。
有两个方式判断中断状态:
1、* Thread实例级方法java.lang.Thread#isInterrupted() 用来检查指定线程的中断状态,true 为中断状态,false 为非中断状态。
Thread实例级方法 java.lang.Thread#interrupted()
调用interrupt并不意味着立即停止目标线程正在执行的工作,而只是传递了请求中断的消息。对中断操作的正确理解是:它并不会真正地中断一个正在运行的线程,而只是发出中断请求,然后由线程在下一个合适的时刻中断自己。(这个时刻也被称为取消点)。很多jdk的方法会识别这个标识并抛出 InterruptedException 相应中断