这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战
LockSupport
类可以阻塞当前线程以及唤醒指定被阻塞的线程。主要是通过park()
和unpark(thread)
方法来实现阻塞和唤醒线程的操作的。
原理:
每个线程都有一个许可(permit
),permit
只有两个值1和0,默认是0。
-
当调用
unpark(thread)
方法,就会将thread
线程的许可permit
设置成1(注意多次调用unpark方法,不会累加,permit值还是1)。 -
当调用
park()
方法,如果当前线程的permit
是1,那么将permit
设置为0,并立即返回。如果当前线程的permit
是0,那么当前线程就会阻塞,直到别的线程将当前线程的permit
设置为1时,park
方法会被唤醒,然后会将permit
再次设置为0,并返回。
注意:因为
permit
默认是0,所以一开始调用park()
方法,线程必定会被阻塞。调用unpark(thread)
方法后,会自动唤醒thread
线程,即park
方法立即返回。
案例:
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
/**
* Description:
*
* @author jack
* @date 2021/8/17 2:56 下午
*/
public class LockSupportTest {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName() + " start");
LockSupport.park();
System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName() + " 被唤醒");
});
t1.setName("t1");
t1.start();
TimeUnit.SECONDS.sleep(2);
LockSupport.unpark(t1);
System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName() + " 执行 LockSupport.unpark() 完毕");
}
}
返回结果
1629184171289,t1 start
1629184173290,main 执行 LockSupport.unpark() 完毕
1629184174291,t1 被唤醒
LockSupport.park()
是否能够响应线程中断?
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
/**
* Description:
*
* @author jack
* @date 2021/8/17 2:56 下午
*/
public class LockSupportTest {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName() + " start");
System.out.println(System.currentTimeMillis() + "," + ",park()之前中断标志:" + Thread.currentThread().isInterrupted());
LockSupport.park();
System.out.println(System.currentTimeMillis() + "," + ",park()之后中断标志:" + Thread.currentThread().isInterrupted());
System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName() + " 被唤醒");
});
t1.setName("t1");
t1.start();
TimeUnit.SECONDS.sleep(2);
t1.interrupt();
System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName() + " 执行 LockSupport.unpark() 完毕");
}
}
返回结果
1629186355905,t1 start
1629186355905,,park()之前中断标志:false
1629186357905,main 执行 LockSupport.unpark() 完毕
1629186357905,,park()之后中断标志:true
1629186357905,t1 被唤醒
LockSupport.park方法让线程等待之后,唤醒方式有2种
- 调用
LockSupport.unpark
方法 - 调用等待线程的
interrupt()
方法,给等待的线程发送中断信号,可以唤醒线程