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 线程进入休眠,外部线程尝试 interrupt
Thread.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 | |
判断当前线程是否被打断 | 判断当前线程是否被打断 |
会清除 打断标记 | 不会清除 打断标记 |