• 技术文章 >Java >java教程

    Java线程的三个同步工具类知识点的汇总,收藏备忘

    php是最好的语言php是最好的语言2018-07-28 16:11:20原创888
    最近面试中遇到Java线程的三个同步工具类的问题,没有复习一时还真想不起来,学多线程的时候也没有仔细学习同步工具类,现在更是忘了。因此我又重温了一遍感觉挺高深的,为了备忘就整理了一下写篇文章,供大家参考。apache php mysql

    Java为我们提供了三个同步工具类

    这几个工具类其实说白了就是为了能够更好控制线程之间的通讯问题~

    一、CountDownLatch

    1.1CountDownLatch简介

    • A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.

    简单来说:CountDownLatch是一个同步的辅助类,允许一个或多个线程一直等待直到其它线程完成它们的操作。

    它常用的API其实就两个:await()countDown()

    1.png

    使用说明:

    1.2CountDownLatch例子

    例子:3y现在去做实习生了,其他的员工还没下班,3y不好意思先走,等其他的员工都走光了,3y再走。

    import java.util.concurrent.CountDownLatch;
    
    public class Test {
    
        public static void main(String[] args) {
    
            final CountDownLatch countDownLatch = new CountDownLatch(5);
    
            System.out.println("现在6点下班了.....");
    
            // 3y线程启动
            new Thread(new Runnable() {
                @Override
                public void run() {
               
                    try {
                        // 这里调用的是await()不是wait()
                        countDownLatch.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("...其他的5个员工走光了,3y终于可以走了");
                }
            }).start();
    
            // 其他员工线程启动
            for (int i = 0; i < 5; i++) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("员工xxxx下班了");
                        countDownLatch.countDown();
                    }
                }).start();
            }
        }
    }

    输出结果:

    2.png

    再写个例子:3y现在负责仓库模块功能,但是能力太差了,写得很慢,别的员工都需要等3y写好了才能继续往下写。

    import java.util.concurrent.CountDownLatch;
    
    public class Test {
    
        public static void main(String[] args) {
    
            final CountDownLatch countDownLatch = new CountDownLatch(1);
    
            // 3y线程启动
            new Thread(new Runnable() {
                @Override
                public void run() {
    
                    try {
                        Thread.sleep(5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("3y终于写完了");
                    countDownLatch.countDown();
    
                }
            }).start();
    
            // 其他员工线程启动
            for (int i = 0; i < 5; i++) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("其他员工需要等待3y");
                        try {
                            countDownLatch.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("3y终于写完了,其他员工可以开始了!");
                    }
                }).start();
            }
        }
    }

    输出结果:

    3.png

    二、CyclicBarrier

    2.1CyclicBarrier简介

    • A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.

    简单来说:CyclicBarrier允许一组线程互相等待,直到到达某个公共屏障点。叫做cyclic是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用(对比于CountDownLatch是不能重用的)

    使用说明:

    2.2CyclicBarrier例子

    例子:3y和女朋友约了去广州夜上海吃东西,由于3y和3y女朋友住的地方不同,自然去的路径也就不一样了。于是他俩约定在体育西路地铁站集合,约定等到相互见面的时候就发一条朋友圈。

    import java.util.concurrent.BrokenBarrierException;
    import java.util.concurrent.CyclicBarrier;
    
    public class Test {
    
        public static void main(String[] args) {
    
            final CyclicBarrier CyclicBarrier = new CyclicBarrier(2);
            for (int i = 0; i < 2; i++) {
    
                new Thread(() -> {
    
                    String name = Thread.currentThread().getName();
                    if (name.equals("Thread-0")) {
                        name = "3y";
                    } else {
                        name = "女朋友";
                    }
                    System.out.println(name + "到了体育西");
                    try {
    
                        // 两个人都要到体育西才能发朋友圈
                        CyclicBarrier.await();
                        // 他俩到达了体育西,看见了对方发了一条朋友圈:
                        System.out.println("跟" + name + "去夜上海吃东西~");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }).start();
            }
        }
    }

    测试结果:

    2.png

    玩了一天以后,各自回到家里,3y和女朋友约定各自洗澡完之后再聊天

    import java.util.concurrent.BrokenBarrierException;
    import java.util.concurrent.CyclicBarrier;
    
    public class Test {
    
        public static void main(String[] args) {
    
            final CyclicBarrier CyclicBarrier = new CyclicBarrier(2);
            for (int i = 0; i < 2; i++) {
    
                new Thread(() -> {
    
                    String name = Thread.currentThread().getName();
                    if (name.equals("Thread-0")) {
                        name = "3y";
                    } else {
                        name = "女朋友";
                    }
                    System.out.println(name + "到了体育西");
                    try {
    
                        // 两个人都要到体育西才能发朋友圈
                        CyclicBarrier.await();
                        // 他俩到达了体育西,看见了对方发了一条朋友圈:
                        System.out.println("跟" + name + "去夜上海吃东西~");
    
                        // 回家
                        CyclicBarrier.await();
                        System.out.println(name + "洗澡");
    
                        // 洗澡完之后一起聊天
                        CyclicBarrier.await();
    
                        System.out.println("一起聊天");
    
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }).start();
            }
        }
    }

    测试结果:

    2.png

    三、Semaphore

    3.1Semaphore简介

    Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource.

    • A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each {@link #acquire} blocks if necessary until a permit is available, and then takes it. Each {@link #release} adds a permit,potentially releasing a blocking acquirer.However, no actual permit objects are used; the {@code Semaphore} just

    keeps a count of the number available and acts accordingly.

    Semaphore(信号量)实际上就是可以控制同时访问的线程个数,它维护了一组"许可证"

    3.2Semaphore例子

    3y女朋友开了一间卖酸奶的小店,小店一次只能容纳5个顾客挑选购买,超过5个就需要排队啦~~~

    import java.util.concurrent.Semaphore;
    
    public class Test {
    
        public static void main(String[] args) {
    
            // 假设有50个同时来到酸奶店门口
            int nums = 50;
    
            // 酸奶店只能容纳10个人同时挑选酸奶
            Semaphore semaphore = new Semaphore(10);
    
            for (int i = 0; i < nums; i++) {
                int finalI = i;
                new Thread(() -> {
                    try {
                        // 有"号"的才能进酸奶店挑选购买
                        semaphore.acquire();
    
                        System.out.println("顾客" + finalI + "在挑选商品,购买...");
    
                        // 假设挑选了xx长时间,购买了
                        Thread.sleep(1000);
    
                        // 归还一个许可,后边的就可以进来购买了
                        System.out.println("顾客" + finalI + "购买完毕了...");
                        semaphore.release();
    
    
    
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }).start();
    
            }
    
        }
    }

    输出结果:

    2.png

    反正每次只能5个客户同时进酸奶小店购买挑选。

    总结:本文简单的介绍了一下Java多线程的三个同步工具类的用处以及如何用,要深入还得看源码或者查阅其他的资料。如果文章有错的地方欢迎指正,大家互相交流。

    相关文章:

    Java基础之线程同步

    关于Java线程同步和同步方法的详解

    相关视频:

    Java多线程与并发库高级应用视频教程

    以上就是Java线程的三个同步工具类知识点的汇总,收藏备忘的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:多线程 java
    上一篇:Java两种动态代理 jdk和cglib生成的代理类型以及如何实现的 下一篇:Java垃圾回收时间也可以轻松降低,实例讲解Ali-HBase的GC
    Web大前端开发直播班

    相关文章推荐

    • Java技巧总结之如何看Lambda源码• 完全掌握Java单例模式• JAVA详细解析之IO流、File、字节流以及字符流• JAVA学习IO操作之字节流和字符流(总结分享)• JAVA面向对象之继承、构造方法、重写和重载(总结分享)
    新人一分购

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网