想看几个例子的效果:
public class LockSupportTest { public static void main(String[] args) { Thread t = new Thread(() -> { for(int i = 0; i < 10; i++) { System.out.println(i); if(i == 5) { LockSupport.park(); } try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } }); t.start(); } }
运行到5后就卡住不动了...
public class LockSupportTest { public static void main(String[] args) { //使用lombda表达式创建一个线程t Thread t = new Thread(() -> { for(int i = 0; i < 10; i++) { System.out.println(i); if(i == 5) { //使用LockSupport的park()方法阻塞当前线程t LockSupport.park(); } try { //使当前线程t休眠1秒 TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } }); //启动当前线程t t.start(); //唤醒线程t LockSupport.unpark(t); } }
控制台每过一秒打印一个数字 到结束。
public class LockSupportTest { public static void main(String[] args) { //使用lombda表达式创建一个线程t Thread t = new Thread(() -> { for(int i = 0; i < 10; i++) { System.out.println(i); if(i == 5) { //使用LockSupport的park()方法阻塞当前线程t LockSupport.park(); } if(i == 8){ //调用LockSupport的park()方法阻塞当前线程t LockSupport.park(); } try { //使当前线程t休眠1秒 TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } }); //启动当前线程t t.start(); //唤醒线程t LockSupport.unpark(t); } }
运行到8的时候又卡住了...
由以上三个小程序我们可以总结得出以下几点:
1、LockSupport不需要synchornized加锁就可以实现线程的阻塞和唤醒
2、LockSupport.unpartk()可以先于LockSupport.park()执行,并且线程不会阻塞
3、如果一个线程处于等待状态,连续调用了两次park()方法,就会使该线程永远无法被唤醒
LockSupport中park()和unpark()方法的实现原理
park()和unpark()方法的实现是由Unsefa类提供的,而Unsefa类是由C和C++语言完成的,其实原理也是比较好理解的,它主要通过一个变量作为一个标识,变量值在0,1之间来回切换,当这个变量大于0的时候线程就获得了“令牌”,从这一点我们不难知道,其实park()和unpark()方法就是在改变这个变量的值,来达到线程的阻塞和唤醒的,具体实现不做赘述了。