目录
1.LockSupport.park():休眠当前线程
2.LockSupport.unpark(线程对象):唤醒某一个指定的线程
3.扩展:LockSupport.parkUntil(long)等待最大时间是一个固定时间
4.LockSupport和Interrupt
5.LockSupport VS wait
相同点:
①二者都能使线程进入休眠状态。
②二者在不传递参数的情况下,都会让线程进入WAITING无限期等待状态。
不同点:
①LockSupport使用时不需要加锁,不需要配合synchronized一起使用;而wait需要配合synchronized一起使用。
②LockSupport不会抛出Interrupt的异常,而wait会。
③LockSupport可以指定某一个线程进行唤醒,而wait和notify不行。
PS:线程休眠4种方式:
有wait和notify是因为sleep只能到点之后再被唤醒,不能主动唤醒。
上述方法的问题:在调用notify时会随机唤醒,无法唤醒指定的某一个线程,不能把握线程唤醒的顺序。
使⽤ LockSupport 也可以使线程休眠和唤醒,它包含两个主要的⽅法↓
注:LockSupport 无需配合 synchronized 使用。
1.LockSupport.park():休眠当前线程
import java.util.concurrent.locks.LockSupport;
public class LockSupportDemo1 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
System.out.println("线程1:开始执行");
LockSupport.park();
System.out.println("线程1:结束执行");
},"线程1");
t1.start();
}
}
2.LockSupport.unpark(线程对象):唤醒某一个指定的线程
import java.util.concurrent.locks.LockSupport;
public class LockSupportDemo1 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
System.out.println("线程1:开始执行");
LockSupport.park();
System.out.println("线程1:结束执行");
},"线程1");
Thread t2 = new Thread(() -> {
System.out.println("线程2:开始执行");
LockSupport.park();
System.out.println("线程2:结束执行");
},"线程2");
Thread t3 = new Thread(() -> {
System.out.println("线程3:开始执行");
LockSupport.park();
System.out.println("线程3:结束执行");
},"线程3");
t1.start();
t2.start();
t3.start();
Thread.sleep(1000);
System.out.println();
LockSupport.unpark(t1); //唤醒线程1开始执行
Thread.sleep(1000);
LockSupport.unpark(t2); //唤醒线程2开始执行
Thread.sleep(1000);
LockSupport.unpark(t3); //唤醒线程3开始执行
}
}
3.扩展:LockSupport.parkUntil(long)等待最大时间是一个固定时间
import java.time.LocalDateTime;
import java.util.concurrent.locks.LockSupport;
public class LockSupportDemo2 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
System.out.println("线程1:开始执行 |" + LocalDateTime.now());
//当前时间 + 超时时间(唤醒时间)
LockSupport.parkUntil(System.currentTimeMillis() + 3000);//3000ms代表3s,表示3s之后恢复执行
System.out.println("线程1:结束执行 |" + LocalDateTime.now());
},"线程1");
t1.start();
}
}
4.LockSupport和Interrupt
之前的 sleep/TimeUnit/wait 写法都需要加try-catch包裹来接收Interrupt异常,写法不够优雅;而 LockSupport.park/parkUntil在休眠时不需要try-catch包裹,不需要接收 Interrupt 异常。
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
LockSupport.park();
LockSupport.parkUntil(1000 + System.currentTimeMillis());
LockSupport 不会抛出 Interrupt 的异常,但可以监听到 Interrupt 的通知:
import java.util.concurrent.locks.LockSupport;
public class ThreadDemo20 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
Thread currThread = Thread.currentThread();
System.out.println("线程中止状态:" + currThread.isInterrupted());
LockSupport.park();
System.out.println("线程中止状态:" + currThread.isInterrupted());
});
t1.start();
Thread.sleep(1000);
System.out.println("中止线程");
t1.interrupt();
LockSupport.unpark(t1);
}
}
5.LockSupport VS wait
相同点:
①二者都能使线程进入休眠状态。
②二者在不传递参数的情况下,都会让线程进入WAITING无限期等待状态。
不同点:
①LockSupport使用时不需要加锁,不需要配合synchronized一起使用;而wait需要配合synchronized一起使用。
②LockSupport不会抛出Interrupt的异常,而wait会。
③LockSupport可以指定某一个线程进行唤醒,而wait和notify不行。
PS:线程休眠4种方式:
- sleep(传参设置休眠时间;不可唤醒)
- TimeUnit(传参设置休眠时间;不可唤醒)
- wait/notify/notifyAll(可传参设置休眠时间,也可不传参无限等待;可以唤醒)
- LockSupport.park()/parkUntil(long)/unpark(thread)(parkUntil可传参设置休眠时间;park不传参无限等待;unpark传参唤醒指定线程)