LockSupport工具类的使用

1. 简介

JDK 中的 rt.jar 包里面的 LockSupport 是个工具类,它的主要作用是挂起和唤醒线程 ,该工具类是创建锁和其他同步类的基础。默认情况下调用LockSupport 类的方法的线程是不持有许可证的。LockSupport 是使用 Unsafe 类实现的


2. 主要方法

1. void park()方法

如果调用 park 方法的线程已经拿到了与 LockSupport 关联的许可证 ,则 调用LockSupport. park()时会马上返回,否则调用线程会被禁止参与线程的调度, 也就是会被阻塞挂起。

package jvm;

import java.util.concurrent.locks.LockSupport;

public class LockSupportDemo {
	public static void main(String[] args) {
		System.out.println("begin park");
		LockSupport.park();
		System.out.println("end park");
	}
}

在这里插入图片描述
2. void unpark(Thread thread)方法

当一个线程调用 unpark时,如果 参数 thread 线程没有持有 thread 与 LockSupport 类关联的许可证,则 让 thread 线程持有。如果 thread 之前因调用 park()而被挂起,则调用unpark 后,该线程会被唤醒 。 如果 thread 之前没有调用 park,则 调用 unpark 方法后 ,再调用 park 方法,其会立刻返 回

测试1:park阻塞->unpark给许可证->解除阻塞

package jvm;

import java.util.concurrent.locks.LockSupport;

public class LockSupportDemo {
	public static void main(String[] args) throws InterruptedException {
		Thread thread=new Thread(()->{
			System.out.println("child thread begin park");
			LockSupport.park();
			System.out.println("child thread unpark");
		});
		thread.start();
		
		Thread.sleep(1000);//主线程休眠1s
		LockSupport.unpark(thread);//调用 unpark方法让 thread线程持有许可证,然后park方法返回
	}
}

在这里插入图片描述

测试2: unpark给许可证->park->立即返回

package jvm;

import java.util.concurrent.locks.LockSupport;

public class LockSupportDemo {
	public static void main(String[] args) throws InterruptedException {
		Thread thread=new Thread(()->{
			try {
				Thread.sleep(1000);//让子线程睡眠1s 保证主线程有机会给许可证
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("child thread begin park");
			LockSupport.park();
			System.out.println("child thread unpark");
		});
		
		thread.start();
		LockSupport.unpark(thread);
		
	}
}

在这里插入图片描述

1次只能有张许可证

package jvm;

import java.util.concurrent.locks.LockSupport;

public class LockSupportDemo {
	public static void main(String[] args) throws InterruptedException {
		System.out.println("begin park");
		LockSupport.unpark(Thread.currentThread());
		LockSupport.unpark(Thread.currentThread());//1次给两张许可证  后面调用两次park
		LockSupport.park();
		LockSupport.park();
		System.out.println("end park");
		
	}
}

在这里插入图片描述

package jvm;

import java.util.concurrent.locks.LockSupport;

public class LockSupportDemo {
	public static void main(String[] args) throws InterruptedException {
		System.out.println("begin park");
		LockSupport.unpark(Thread.currentThread());
		LockSupport.park();
		LockSupport.unpark(Thread.currentThread());
		LockSupport.park();
		System.out.println("end park");
		
	}
}

在这里插入图片描述

3. void parkNanos(long nanos)方法

和 park 方法类似,不同点在于如果没有拿到许可证,则调用线程会被挂起 nanos 时间后修改为自动返回。

import java.util.concurrent.locks.LockSupport;

public class LockSupportDemo {
	public static void main(String[] args) throws InterruptedException {
		System.out.println("begin park");
		long startTime=System.currentTimeMillis();//获取当前系统毫秒数
		LockSupport.parkNanos(2000000000L);//1ms=10^6ns  设置时长2000ms 2s后自动返回
		System.out.println(System.currentTimeMillis()-startTime);
		System.out.println("end park");
		
	}
}

在这里插入图片描述
4. void parkUtil(long deadline)

import java.util.Date;
import java.util.concurrent.locks.LockSupport;

public class LockSupportDemo {
	public static void main(String[] args) throws InterruptedException {
		
		long nowMills=new Date().getTime();
		System.out.println("begin park");
		LockSupport.parkUntil(nowMills+5000);//当前时间再过5s阻塞结束
		System.out.println("end park");
		
	}
}

在这里插入图片描述


3. LockSupport.park()和Thread.sleep()的区别

  1. Thread.sleep()没法从外部唤醒,只能自己醒过来;而被LockSupport.park()方法阻塞的线程可以通过调用LockSupport.unpark()方法去唤醒
  2. Thread.sleep()方法声明了InterruptedException中断异常,这是一个受检异常,调用者需要捕获这个异常或者再抛出;而调用LockSupport.park()方法时不需要捕获中断异常
  3. Thread.sleep()本身就是一个Native方法;LockSupport.park()并不是一个Native方法,只是调用了一个Unsafe类的Native方法(名字也叫park)去实现
  4. 当被阻塞线程的Thread.interrupt()方法被调用时,LockSupport.park()方法不会抛出InterruptedException异常,仅仅设置了线程的中断标志;而Thread.sleep()方法会抛出InterruptedException异常

不管是sleep还是park,线程进入阻塞状态后都不会释放锁


4. LockSupport.park()与Object.wait()的区别

  1. Object.wait()方法需要在synchronized块中执行,而LockSupport.park()可以在任意地方执行
  2. 当被阻塞线程被中断时,Object.wait()方法抛出了中断异常,调用者需要捕获或者再抛出;当被阻塞线程被中断时,LockSupport.park()不会抛出异常,调用时不需要处理中断异常
  3. 只能先wait再notify, 但是可以先unpark再park
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodePanda@GPF

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值