目录
在某个线程中,调用该方法会阻塞住该线程。用park阻塞住的线程,想要唤醒它,有两种方法:一种是 LockSupport.unpark(),另一种是中断。
一:LockSupport.unpark()唤醒线程:
public static void main(String[] args) {
Thread t0 = new Thread(new Runnable() {
@Override
public void run() {
Thread current = Thread.currentThread();
log.info("{},开始执行!",current.getName());
for(;;){
log.info("准备park住当前线程:{}....",current.getName());
LockSupport.park(); // 或者是LockSupport.park(this);
log.info("当前线程{}已经被唤醒....",current.getName());
}
}
},"t0");
t0.start();
try {
Thread.sleep(2000);
log.info("准备唤醒{}线程!",t0.getName());
LockSupport.unpark(t0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
运行结果:
LockSupport.unpark()只会唤醒该线程一次。下次用LockSupport.park()再次阻塞住的时候,需要再次调用LockSupport.unpark()唤醒该线程。简言之,利用LockSupport.unpark()唤醒线程,该方法需要与LockSupport.park()方法成对出现,每次park都有对应的unpark。
二:中断
不清除中断标记
public static void main(String[] args) {
Thread t0 = new Thread(new Runnable() {
@Override
public void run() {
Thread current = Thread.currentThread();
log.info("{},开始执行!",current.getName());
for(;;){
log.info("准备park住当前线程:{}....",current.getName());
LockSupport.park(); // 或者是LockSupport.park(this);
// Thread.interrupted();
log.info("当前线程{}已经被唤醒....",current.getName());
}
}
},"t0");
t0.start();
try {
Thread.sleep(2000);
log.info("准备唤醒{}线程!",t0.getName());
t0.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
运行结果:
利用Thread类中的 public void interrupt() 方法,发出一个中断,也会唤醒park方法阻塞住的线程。
但是当下次再循环到park方法时,不再阻塞住线程,循环会一直执行。
清除中断标记
若打开上述代码中第10行的的注释,// Thread.interrupted();
public static void main(String[] args) {
Thread t0 = new Thread(new Runnable() {
@Override
public void run() {
Thread current = Thread.currentThread();
log.info("{},开始执行!",current.getName());
for(;;){
log.info("准备park住当前线程:{}....",current.getName());
LockSupport.park(); // 或者是LockSupport.park(this);
Thread.interrupted();
log.info("当前线程{}已经被唤醒....",current.getName());
}
}
},"t0");
t0.start();
try {
Thread.sleep(2000);
log.info("准备唤醒{}线程!",t0.getName());
t0.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
运行结果:
会发现等到下次循环再次遇到 LockSupport.park() 时依旧可以阻塞住。
注释的那行有什么作用呢?
这是因为调用 t0.interrupt() 方法发出一个中断时,t0线程上面会一个中断状态(打上一个中断标记)。当发出的中断唤醒了 LockSupport.park() 方法阻塞住的线程时,park方法发现 t0线程有这个中断状态,知道该线程是需要被中断处理的,则下一次调用 LockSupport.park() 则不会再被阻塞了。
如果发出了中断后,唤醒了 LockSupport.park() 阻塞的线程,下一次遇到 LockSupport.park() 还想被阻塞住,就需要先调用 Thread.interrupted() 方法来清除中断状态,这样下一次遇到 LockSupport.park() 方法的时候,线程便会被阻塞住。