sleep()
public void testSleepAndYield() {Thread t1 = new Thread(() -> {try {log.debug("t1-sleep...");Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}}, "t1");log.debug("t1 start 前的状态:{}",t1.getState()); // NEW 创建t1.start();log.debug("t1 start 后的状态:{}",t1.getState()); // RUNNABLE 就绪 => t1 线程刚创建,还未 sleep// 让主线程等待一会儿,等 t1 线程 sleep 时,查看 t1 线程的状态try {Thread.sleep(500);} catch (InterruptedException e) {throw new RuntimeException(e);}log.debug("t1 sleep 时的状态:{}",t1.getState()); // TIMED_WAITING 阻塞
}
16:34:01:196 [main] c.Test2 - t1 start 前的状态:NEW
16:34:01:198 [main] c.Test2 - t1 start 后的状态:RUNNABLE
16:34:01:199 [t1] c.Test2 - t1-sleep...
16:34:01:708 [main] c.Test2 - t1 sleep 时的状态:TIMED_WAITING
- 调用 sleep 会让当前线程从 Running 进入 Timed Waiting 状态(阻塞)
- 其它线程可以使用 interrupt 方法打断正在睡眠的线程,这时 sleep 方法会抛出 InterruptedException
- 睡眠结束后的线程未必会立刻得到执行
- 建议用 TimeUnit 的 sleep 代替 Thread 的 sleep 来获得更好的可读性
join()
static int i = 0;public static void main(String[] args) throws InterruptedException {test1();}private static void test1() throws InterruptedException {Thread t1 = new Thread(() -> {try {Thread.sleep(1000);i = 10;} catch (InterruptedException e) {throw new RuntimeException(e);}}, "t1");t1.start();// 让当前线程等待 t1 线程结束t1.join();log.debug("结果为:{}", i);}
未调用 join 方法
17:04:04:422 [main] c.TestJoin - 结果为:0
调用 join 方法
17:01:37:312 [main] c.TestJoin - 结果为:10
等待当前线程运行结束
join(long n):等待线程运行结束,最多等待 n 毫秒。
Interrupt()
打断 sleep,wait,join 的线程,这几个方法都会让线程进入阻塞状态
打断 sleep 的线程, 会清空打断状态
@Test
public void testInterrupt() throws InterruptedException {Thread t1 = new Thread(() -> {try {log.debug("sleeping");// 让 t1 线程进入休眠,外部线程尝试 interruptThread.sleep(5000);} catch (InterruptedException e) {throw new RuntimeException(e);}}, "t1");t1.start();Thread.sleep(1000);log.debug("interrupt");t1.interrupt();log.debug("是否被打断:{}",t1.isInterrupted());
}
可以看到t1 sleep 一秒后已经被打断了,且抛出了 InterruptedException: sleep interrupted
异常,但是查询t1的打断状态缺失,显示未打断,说明 sleep 时线程被 interrupt 后,清除了 interrupt 的状态。
打断正常运行的线程,不会清除打断状态
private static void test1() {Thread t1 = new Thread(() -> {while (true){Thread current = Thread.currentThread();// 查看当前线程是否被打断boolean interrupted = current.isInterrupted();if (interrupted){log.debug("t1-interrupt...");break;}}}, "t1");t1.start();log.debug("interrupt");t1.interrupt();log.debug("是否被打断:{}",t1.isInterrupted());
}
注意 interrupt() 和 isInterrupted() 方法的区别
interrupted() | isInterrupted() |
---|---|
static | |
判断当前线程是否被打断 | 判断当前线程是否被打断 |
会清除 打断标记 | 不会清除 打断标记 |