LockSupport类是JDK种rt.jar包中的工具类,它主要的作用是挂起和唤醒,该工具类是创建锁和其他同步类的基础。
LockSupport类采用的是许可证机制,该类与使用它的线程都会关联一个许可证,在默认情况下调用LockSupport类方法的线程是不存在许可证的。LockSupport是使用UnSafe类实现的。
LockSupport的park()方法与unpart(Thread thread)方法
park():线程调用LockSupport.park()方法,首先需要判断该线程是否持有许可证,如果没有持有,则该线程阻塞挂起,直至获得许可证;如果该线程已持有许可证,线程会继续执行。
unpark(Thread thread):线程调用LockSupport.unpark()方法,给该线程发放许可证,如果线程调用park()方法阻塞挂起,则唤醒该线程继续执行,如果在该方法之后调用park()方法,线程会继续执行,不会被阻塞。
示例代码如下
/**
* 调用LockSupport.park()的线程类
*/
public class PartThread extends Thread{
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("线程"+Thread.currentThread().getId()+"begin park");
LockSupport.park();
System.out.println("线程"+Thread.currentThread().getId()+"end park");
}
}
/**
* 调用LockSupport.unpark(Thread thred)方法的线程类
*/
public class UnpartThread extends Thread{
private PartThread partThread;
public UnpartThread(PartThread partThread) {
this.partThread=partThread;
}
@Override
public void run() {
System.out.println("线程"+Thread.currentThread().getId()+"-执行unpart前-----------");
LockSupport.unpark(partThread);
System.out.println("线程"+Thread.currentThread().getId()+"-执行unpart后-----------");
}
}
测试代码:
public class Demo {
public static void main(String[] args) {
PartThread partThread = new PartThread();
UnpartThread unpartThread=new UnpartThread(partThread);
partThread.start();
unpartThread.start();
}
}
测试结果:
从结果上看,线程是先调用unpark()方法,而后再调用park()方法。所以线程调用park()前已存在许可证,从而调用park()之后没有进入阻塞状态,继续执行。
那如果先调用notify()方法,在调用wait()方法会产生什么样的结果呢?会和使用park()方法和unpark方法一样吗?可先思考一下该问题,在继续往下看。
wait()与notify()方法
wait():线程调用wait()后,线程进入阻塞状态,直至该线程调用notify()方法或notifyAll(),该线程从阻塞状态进入可运行状态。
notify():唤醒等待中的线程
示例代码如下:
/**
* 调用wait()方法的线程类
*/
public class WaitThrad extends Thread {
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println("线程"+Thread.currentThread().getId()+"begin wait");
synchronized (this){
wait();
}
System.out.println("线程"+Thread.currentThread().getId()+"end wait");
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 调用notify()方法的线程类
*/
public class NotifyThread extends Thread{
private WaitThrad waitThrad;
public NotifyThread(WaitThrad waitThrad) {
this.waitThrad = waitThrad;
}
@Override
public void run() {
System.out.println("线程"+Thread.currentThread().getId()+"-执行notify前-----------");
synchronized (waitThrad){
waitThrad.notify();
}
System.out.println("线程"+Thread.currentThread().getId()+"-执行notify后-----------");
}
}
测试代码:
public class Demo {
public static void main(String[] args) {
WaitThrad waitThrad = new WaitThrad();
NotifyThread notifyThread=new NotifyThread(waitThrad);
waitThrad.start();
notifyThread.start();
}
}
测试结果:
由结果可看出,notify()方法是在线程调用wait()方法前执行的。这个时候线程调用wait()方法,wait()方法线程一直处于阻塞等待状态。
所以,在调用wait()方法之前调用notify()方法,wait()方法会错失信号,进入无限等待状态,从而产生死锁。
还有一点区别,就是wait()方法和notify()方法需要与sychronized锁机制一起使用,否则会产生java.lang.IllegalMonitorStateException异常,这个有兴趣的话可以去除sychronized锁机制,自己尝试一下
总结:
park()与unpark()方法:只要线程存在许可证,不管是在park()方法前或者调用park()方法后拥有,线程都会继续执行。
wait()与notify()方法:wait()方法必须要在notify()方法之前执行,否则wait()方法错失信号,进入无限等待状态,从而产生死锁