在java中,线程休眠就是让线程进入BLOCKED阻塞状态,在线程结束休眠后进入RUNNABLE可运行状态。线程休眠可以分为指定时间的休眠和无限期休眠,指定时间休眠是设置时间,时间到了自动唤醒;无期限休眠是通过休眠和唤醒方法控制线程的状态。
线程休眠的常用方法有Thread.sleep()、TimeUnit.*.sleep()、Object.wait()/notity()、LockSupport.park()/unpark()。其中前两个是让线程休眠指定时间后自动唤醒,后两个提供了一对休眠和唤醒的方法,实现线程状态的切换。
1、Thread.sleep()
Thread.sleep 方法需要传递一个 long 类型的毫秒数,表示 n 毫秒之后自动唤醒,示例如下
Thread t1 = new Thread() {
@Override
public void run() {
System.out.printf("%s线程执行:%s\n",Thread.currentThread().getName(), LocalDateTime.now());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("%s线程结束:%s\n",Thread.currentThread().getName(),LocalDateTime.now());
}
};
t1.start();
2、TimeUnit.*.sleep()
TimeUnit可以指定休眠的时间类型,如设置小时、分钟,和第一个类似,示例如下
Thread t1 = new Thread() {
@Override
public void run() {
System.out.printf("%s线程执行:%s\n",Thread.currentThread().getName(), LocalDateTime.now());
try {
TimeUnit.SECONDS.sleep(1);
//TimeUnit.DAYS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("%s线程结束:%s\n",Thread.currentThread().getName(),LocalDateTime.now());
}
};
t1.start();
3、Object.wait()/notity()
wait()/notity()来自于Object类,wait() 方法表示让当前线程无限期等待下去,直到遇到 notify/notifyAll 方法时才会被唤醒,示例如下
Object obj = new Object();
new Thread(() -> {
try {
synchronized (obj) {
// 让当前线程休眠
System.out.println("等待开始");
obj.wait();
System.out.println("等待结束");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 唤醒当前对象上一个休眠线程
synchronized (obj) {
obj.notify();
System.out.println("唤醒");
}
4、LockSupport.park()/unpark()
LockSupport 是更加底层的操作线程休眠和唤醒的对象,和第三个类似,示例如下
Thread t1 = new Thread(() -> {
System.out.println("线程1休眠开始");
LockSupport.park(); // 休眠线程
System.out.println("线程1执行结束");
}, "线程1");
t1.start();
Thread t2 = new Thread(() -> {
System.out.println("线程2休眠开始");
LockSupport.park(); // 休眠线程
System.out.println("线程2执行结束");
}, "线程2");
t2.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 唤醒线程1
LockSupport.unpark(t1);
System.out.println("唤醒线程1");