zoukankan      html  css  js  c++  java
  • Java多线程系列——线程阻塞工具类LockSupport

    简述

    LockSupport 是一个非常方便实用的线程阻塞工具,它可以在线程内任意位置让线程阻塞。

    和 Thread.suspend()相比,它弥补了由于 resume()在前发生,导致线程无法继续执行的情况。

    和 Object.wait()相比,它不需要先获得某个对象的锁,也不会抛出 InterruptedException 异常。

    LockSupport 的静态方法 park()可以阻塞当前线程,类似的还有 parkNanos()、parkUntil()等方法。它们实现了一个限时等待,如下图所示:

    实例

     1 import java.util.concurrent.locks.LockSupport;
     2 /**
     3  * Created by zhengbinMac on 2017/3/5.
     4  */
     5 public class SuspendResumeTest {
     6     public static Object object = new Object();
     7     static TestThread t1 = new TestThread("线程1");
     8     static TestThread t2 = new TestThread("线程2");
     9     public static class TestThread extends Thread{
    10         public TestThread(String name) {
    11             super.setName(name);
    12         }
    13         @Override
    14         public void run() {
    15             synchronized (object) {
    16                 System.out.println(getName()+" 占用。。");
    17 //                Thread.currentThread().suspend();
    18                 LockSupport.park();
    19                 System.out.println(Thread.currentThread().getName()+" 执行结束!");
    20             }
    21         }
    22     }
    23     public static void main(String[] args) throws InterruptedException {
    24         t1.start();
    25         Thread.sleep(200);
    26         t2.start();
    27 //        t1.resume();
    28         LockSupport.unpark(t1);
    29         LockSupport.unpark(t2);
    30 //        t2.resume();
    31         t1.join();
    32         t2.join();
    33     }
    34 }

    代码只是对Java多线程——过期的suspend()挂起、resume()继续执行线程中实例稍作修改,将 suspend()和 resume()改为 park()与 unpark()。

    修改后,同样的问题:我们依然无法保证 unpark()方法发生在 park()之后,但是多次执行代码,发现始终都可以正常结束,不会因为两方法的顺序导致线程永久性挂起。

    这是因为,其使用类似信号量的机制。

    它为每个线程准备了一个许可,如果许可可用,那么 park()方法立即返回,并消费这个许可(将许可变为不可用);如果许可不可用,则阻塞。

    而 unpark()方法,则是使一个许可变为可用。

    上述特点使得:即使 unpark()操作发生在 park()之前,它也可以使下一次得 park()操作立即返回。这是上述实例代码顺利结束的原因。

    同时,park()挂起的线程不会像 suspend()那样线程状态为 RUNNABLE,park()会明确给出 WAITING 状态,并标注由 park()引起,如下图所示:

    这个标注,使得分析问题时更加方便,可以使用 park(Object)方法,为当前线程设置一个阻塞对象,这个阻塞对象会出现在线程 Dump 中。

    将实例中 18 行改为:

    LockSupport.park(this);

    jstack 输出为:

    参考资料

    [1] 实战Java高并发程序设计, 3.1.7 - 线程阻塞工具类:LockSupport

    [2] Java并发编程的艺术, 5.5 - LockSupport工具

  • 相关阅读:
    vim字体设置
    windows下eclipse打不开
    ubuntu的无线网无法连上
    将ubuntu系统录到u盘上
    使用UltraISO刻录系统到U盘可能会出现打不开的情况
    windows安装程序制作
    安装ubuntu双系统
    数据库插入数据时间比较
    LeetCode 189. Rotate Array
    LeetCode 228. Summary Ranges
  • 原文地址:https://www.cnblogs.com/zhengbin/p/6506166.html
Copyright © 2011-2022 走看看