首页 技术 正文
技术 2022年11月10日
0 收藏 654 点赞 3,288 浏览 4155 个字

LockSupport是用来创建锁和其他同步类的基本线程阻塞原语。
LockSupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程,而且park()和unpark()不会遇到“Thread.suspend 和 Thread.resume所可能引发的死锁”问题。
因为park() 和 unpark()有许可的存在;调用 park() 的线程和另一个试图将其 unpark() 的线程之间的竞争将保持活性。

基本用法
LockSupport 很类似于二元信号量(只有1个许可证可供使用),如果这个许可还没有被占用,当前线程获取许可并继 续 执行;如果许可已经被占用,当前线 程阻塞,等待获取许可。

?

12345 public static void main(String[] args){   LockSupport.park();   System.out.println("block.");}

运行该代码,可以发现主线程一直处于阻塞状态。因为 许可默认是被占用的 ,调用park()时获取不到许可,所以进入阻塞状态。

如下代码:先释放许可,再获取许可,主线程能够正常终止。LockSupport许可的获取和释放,一般来说是对应的,如果多次unpark,只有一次park也不会出现什么问题,结果是许可处于可用状态。

?

1234567 public static void main(String[] args){   Thread thread = Thread.currentThread();   LockSupport.unpark(thread);//释放许可   LockSupport.park();// 获取许可   System.out.println("b");}

LockSupport是可不重入 的,如果一个线程连续2次调用 LockSupport .park(),那么该线程一定会一直阻塞下去。

?

123456789101112 public static void main(String[] args) throws Exception{ Thread thread = Thread.currentThread();   LockSupport.unpark(thread);   System.out.println("a"); LockSupport.park(); System.out.println("b"); LockSupport.park(); System.out.println("c");}

这段代码打印出a和b,不会打印c,因为第二次调用park的时候,线程无法获取许可出现死锁。

下面我们来看下LockSupport对应中断的响应性

?

12345678910111213141516171819202122232425262728293031323334353637 public static void t2() throws Exception{ Thread t = new Thread(new Runnable() {  private int count = 0;   @Override  public void run()  {   long start = System.currentTimeMillis();   long end = 0;    while ((end - start) <= 1000)   {    count++;    end = System.currentTimeMillis();   }    System.out.println("after 1 second.count=" + count);   //等待或许许可   LockSupport.park();   System.out.println("thread over." + Thread.currentThread().isInterrupted());   } });  t.start();  Thread.sleep(2000);  // 中断线程 t.interrupt();    System.out.println("main over");}

最终线程会打印出thread over.true。这说明 线程如果因为调用park而阻塞的话,能够响应中断请求(中断状态被设置成true),但是不会抛出InterruptedException 。

LockSupport函数列表

?

12345678910111213141516 // 返回提供给最近一次尚未解除阻塞的 park 方法调用的 blocker 对象,如果该调用不受阻塞,则返回 null。static Object getBlocker(Thread t)// 为了线程调度,禁用当前线程,除非许可可用。static void park()// 为了线程调度,在许可可用之前禁用当前线程。static void park(Object blocker)// 为了线程调度禁用当前线程,最多等待指定的等待时间,除非许可可用。static void parkNanos(long nanos)// 为了线程调度,在许可可用前禁用当前线程,并最多等待指定的等待时间。static void parkNanos(Object blocker, long nanos)// 为了线程调度,在指定的时限前禁用当前线程,除非许可可用。static void parkUntil(long deadline)// 为了线程调度,在指定的时限前禁用当前线程,除非许可可用。static void parkUntil(Object blocker, long deadline)// 如果给定线程的许可尚不可用,则使其可用。static void unpark(Thread thread)


LockSupport示例
对比下面的“示例1”和“示例2”可以更清晰的了解LockSupport的用法。
示例1

?

123456789101112131415161718192021222324252627282930313233343536 public class WaitTest1 {   public static void main(String[] args) {     ThreadA ta = new ThreadA("ta");     synchronized(ta) { // 通过synchronized(ta)获取“对象ta的同步锁”      try {        System.out.println(Thread.currentThread().getName()+" start ta");        ta.start();         System.out.println(Thread.currentThread().getName()+" block");        // 主线程等待        ta.wait();         System.out.println(Thread.currentThread().getName()+" continue");      } catch (InterruptedException e) {        e.printStackTrace();      }    }  }   static class ThreadA extends Thread{     public ThreadA(String name) {      super(name);    }     public void run() {      synchronized (this) { // 通过synchronized(this)获取“当前对象的同步锁”        System.out.println(Thread.currentThread().getName()+" wakup others");        notify();  // 唤醒“当前对象上的等待线程”      }    }  }}

示例2

?

1234567891011121314151617181920212223242526272829303132333435 import java.util.concurrent.locks.LockSupport; public class LockSupportTest1 {   private static Thread mainThread;   public static void main(String[] args) {     ThreadA ta = new ThreadA("ta");    // 获取主线程    mainThread = Thread.currentThread();     System.out.println(Thread.currentThread().getName()+" start ta");    ta.start();     System.out.println(Thread.currentThread().getName()+" block");    // 主线程阻塞    LockSupport.park(mainThread);     System.out.println(Thread.currentThread().getName()+" continue");  }   static class ThreadA extends Thread{     public ThreadA(String name) {      super(name);    }     public void run() {      System.out.println(Thread.currentThread().getName()+" wakup others");      // 唤醒“主线程”      LockSupport.unpark(mainThread);    }  }}

运行结果:

?

1234 main start tamain blockta wakup othersmain continue

说明:park和wait的区别。wait让线程阻塞前,必须通过synchronized获取同步锁。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,493
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,907
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,740
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,495
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,133
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,297