LockSupport的使用


LockSupport

1、简单概述

能够对线程进行阻塞的工具类,不止是只有对象中的wait方法才可以来进行实现。

2、几个DEMO测试

/**
 * @Description 简单介绍一下LockSupport的使用  https://blog.csdn.net/shijiejiujiuba/article/details/79034307
 * @Author liguang
 * @Date 2022/03/10/00:15
 */
public class ThreadWattingTestOne {
    public static void main(String[] args) {
        final Thread thread1 = new Thread(() -> {
            int i = 0;
            do {
                i++;
            } while (i != 10000);
            LockSupport.unpark(Thread.currentThread());
            System.out.println("hello,world");
            LockSupport.park();
            System.out.println("hello,park");
            LockSupport.park();
        });
        thread1.start();
        try {
            thread1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

LockSupport.unpark(Thread.currentThread());表示的是擦除当前线程的许可(因为默认是被something占据的),然后LockSupport.park()表示的是占用当前许可,然后有了许可之后,即可向下执行;但是发现又有LockSupport.park(),但是因为许可已经被占用了,那么这个就只能够阻塞在这里,等待拥有许可之后再来执行下面的,所以只会输出hello,world和hello,park

/**
 * @Description 让线程之间进行交互
 * @Author liguang
 * @Date 2022/03/10/00:15
 */
public class ThreadWattingTestTwo {
    public static void main(String[] args) {
         Thread thread1 = new Thread(() -> {
            LockSupport.park();
            System.out.println("hello,threadone............");
        });
        try {
            thread1.start();
            Thread.sleep(10000);
            LockSupport.unpark(thread1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

因为默认的许可是被占据的,但是在主线程中10s钟被唤醒了,所以会输出hello,threadone............

/**
 * @Description 线程如果因为调用park而阻塞的话,能够响应中断请求(中断状态被设置成true),但是不会抛出InterruptedException。
 * @Author liguang
 * @Date 2022/03/10/00:15
 */
public class ThreadWattingThree {
    public static void main(String[] args) {
         Thread thread1 = new Thread(() -> {
            LockSupport.park();
            System.out.println("hello,threadone............");
        });
        try {
            thread1.start();
            Thread.sleep(10000);
            thread1.interrupt();
            System.out.println("hello,world");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

这里因为线程许可被默认占用了,所以会一直阻塞,然后在10秒钟之后,会被中断,因为中断,所以导致线程被唤醒(但是没有抛出异常),所以会输出:

hello,threadone............
hello,world

那么接着上面的测试:

/**
 * @Description 因为中断引起的,那么将导致利用工具类再次进行Park的时候无法进行park住的操作,这里是因为在检测过程中查看到是中断状态,所以不会去中断
 * @Author liguang
 * @Date 2022/03/10/00:15
 */
public class ThreadWattingThree {
    public static void main(String[] args) {
         Thread thread1 = new Thread(() -> {
             for (;;){
                 LockSupport.park();
                 System.out.println("hello,threadone............");
             }
        });
        try {
            thread1.start();
            Thread.sleep(10000);
            thread1.interrupt();
            System.out.println("hello,world");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

这里对于新创建的线程来说,会不断的输出

hello,threadone..........

因为LockSupport.park();在进行阻塞的时候,发现线程已经被打上了中断标记了,所以不在阻塞,因为让线程继续运行。

那么与之对应的就有另外一个方法可以来进行实现:

/**
 * @Description 因为中断引起的,那么将不会阻塞住;所以这里使用工具类将线程的中断标记给清除掉,对于线程的Thread.interupted的测试来测试一下
 * @Author liguang
 * @Date 2022/03/10/00:15
 */
public class ThreadWattingFour {

    public static void main(String[] args) {
         Thread thread1 = new Thread(() -> {
             for (;;){
                 LockSupport.park("Lock");
                 System.out.println("hello,threadone............");
                 // 但是在这里加上一行数据即可
                 // Thread.interrupted();
             }
        });
        try {
            thread1.start();
            Thread.sleep(1000);
            // 因为中断引起的线程不在阻塞
            thread1.interrupt();
            System.out.println("hello,world");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

这里是一个带参数的,而另外的地方是不带参数的。所以这样子来直接进行实现的时候,效果上是一样的。

其中:中断是可以取消线程进行阻塞的,只需要在上面的代码中加上:

 Thread.interrupted();

擦除掉线程的中断状态即可。

处于waitting状态不会消耗CPU,但是CPU的切换需要消耗CPU

https://baijiahao.baidu.com/s?id=1712014506366682907&wfr=spider&for=pc