常用的辅助类

8. 常用的辅助类

8.1 CountDownLatch

在这里插入图片描述
//计数器
public class CountDownLatchDemo {

    public static void main(String[] args) throws InterruptedException {
        // 倒计时总数是6, 必须要执行任务的时候,再使用!
        CountDownLatch countDownLatch = new CountDownLatch(6);
        for (int i = 0; i < 6; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName() + " GO out");
                countDownLatch.countDown();     //数量减1
            },String.valueOf(i)).start();
        }
        countDownLatch.await();// 等待计数器归零,然后再向下执行

        System.out.println("close Door");
    }

}

原理:

countDownLatch.countDown(); //数量减1

countDownLatch.await();// 等待计数器归零,然后再向下执行

每次有线程调用countDown()数量-1,假设计数器变为0,countDownLatch.await();就会被唤醒,继续执行

8.2 cyclicBarrier

在这里插入图片描述

加法计数器

public class CyclicBarrierDemo {

    public static void main(String[] args) {
        /**
         * 集齐77个龙珠召唤神龙
         */
        // 召唤龙珠的线程
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7, ()->{
            System.out.println("召唤神龙成功! ");
        });
        for (int i = 0; i < 7; i++) {
            int temp = i;
            //lambda 能拿到i吗
            new Thread(()->{
                System.out.println(Thread.currentThread().getName() + "收集" + temp + "个龙珠");

                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

为什么 Lambda 表达式(匿名类) 不能访问非 final 的局部变量呢?
因为实例变量存在堆中,而局部变量是在栈上分配,Lambda 表达(匿名类) 会在另一个线程中执行。如果在线程中要直接访问一个局部变量,可能线程执行时该局部变量已经被销毁了,而 final 类型的局部变量在 Lambda 表达式(匿名类) 中其实是局部变量的一个拷贝。
当成员变量中引用了局部变量,那么就需要加final,复制一份到内存中,否则引用的该变量就访问不到了。
JDK1.8之后匿名内部类访问方法中的局部变量不用加final修饰

image.png

CyclicBarrier:指定个数线程执行完毕再执行操作。
Semaphore:同一时间只能有指定数量个得到线程。

8.3 Semaphore

在这里插入图片描述
public class SemaphoreTest {

    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3);

        for (int i = 0; i < 6; i++) {
            int temp = i;
            new Thread(()->{
                try {
                    semaphore.acquire(); //获取
                    System.out.println(temp + "号车抢到车位");
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release(); //释放
                    System.out.println(temp + "号车离开车位");
                }
            }).start();
        }
    }
}

原理:

semaphore.acquire(); //获取信号量,假设如果已经满了,等待信号量可用时被唤醒

semaphore.release(); //释放信号量

作用: 多个共享资源互斥的使用!并发限流,控制最大的线程数

你可能感兴趣的:(常用的辅助类)