美文网首页
十四、同步器

十四、同步器

作者: blank_white | 来源:发表于2020-07-19 20:58 被阅读0次

十四、同步器

倒计时门栓

倒计时门栓 设置倒计时数,倒计时减到 0 时,await的线程才能通过
适用于线程运行需要其他线程将数据准备好


        // 倒计时门栓 设置倒计时数,倒计时减到 0 时,await的线程才能通过
        // 适用于线程运行需要其他线程将数据准备好
        CountDownLatch countDownLatch = new CountDownLatch(1);

        int[] nums={0,0,0};
        new Thread(()->{
            try {
                // 等待数据准备
                countDownLatch.await();
                // 可以设置等待时间,超过时间直接不等了,继续往下执行
                //countDownLatch.await(10, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            nums[0]++;
            System.out.println("执行");
        }).start();

        Thread.sleep(1000);
        // 数据准备好了
        nums[0]=1;
        System.out.println("cutDown");
        // 计数器-1 ,计数到 0 ,线程能继续运行了
        countDownLatch.countDown();
障栅

障栅 ,适用于 当需要都所有线程都运行到一个位置,才能继续运行下去的时候

        // 障栅 ,适用于 当需要都所有线程都运行到一个位置,才能继续运行下去的时候
        // 参数:线程数
        // CyclicBarrier 是可以复用的,当所有线程有到达障栅之后,便可以进行下次复用
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
        // 可以传入一个 Runnable 当所有线程都到达障栅的时候执行(执行一次,而不是每个线程都执行一次)
        // CyclicBarrier cyclicBarrier =new CyclicBarrier(3,()-> System.out.println("所有线程都到达障栅"));
        new Thread(()->{
            try {
                System.out.println("1 需要等待");
                cyclicBarrier.await();
                System.out.println("1 继续");
            } catch (Exception e){
                e.printStackTrace();
            }
        }).start();

        new Thread(()->{
            try {
                System.out.println("2 需要等待");
                cyclicBarrier.await();
                // 如果设置了等待时间,则超时后或者await方法被中断,所有线程的await方法都会抛出 BrokenBarrier 异常
                //cyclicBarrier.await(1, TimeUnit.NANOSECONDS);
                System.out.println("2 继续");
            } catch (Exception e){
                e.printStackTrace();
            }
        }).start();
        new Thread(()->{
            try {

                Thread.sleep(2000);
                System.out.println("3 需要等待");
                cyclicBarrier.await();
                System.out.println("3 继续");
            } catch (Exception e){
                e.printStackTrace();
            }
        }).start();
交换器

可以让两个线程交换数据 ,可以用于如:两块数据区 分别用于生产者和消费者,生产者生产满了,消费者消费完了,二者交换数据区

        // 可以让两个线程交换数据 ,可以用于如:两块数据区 分别用于生产者和消费者,生产者生产满了,消费者消费完了,二者交换数据区
        Exchanger<Integer> exchanger = new Exchanger();

        new Thread(()->{
           Integer num= 1;
           try {
               // 等待交换数据,返回值为另一个线程提供的数据
               num=exchanger.exchange(num);
               System.out.println("线程1:"+num);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
        }).start();

        new Thread(()->{
            Integer num= 2;
            try {
                num=exchanger.exchange(num);
                System.out.println("线程2:"+num);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        // 线程2 :1
        // 线程1  :2

同步队列

一个线程将数据传递给另一个线程

        // 一个线程调用 put 方法时,会阻塞至另一线程调用 take方法 为止
        // 因为实现了 BlockingQueue 接口,所以调用take 方法时,如果还没有 put 也会阻塞
        SynchronousQueue synchronousQueue = new SynchronousQueue();

        new Thread(()->{
            try {
                synchronousQueue.put(1);
                System.out.println("put");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(()->{
            try {
                Thread.sleep(1000);
                System.out.println("take");
                synchronousQueue.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        // take
        // put

相关文章

网友评论

      本文标题:十四、同步器

      本文链接:https://www.haomeiwen.com/subject/tarqkktx.html