zoukankan      html  css  js  c++  java
  • JUC------03

    1.1 线程通信

    1.1.1 CountDownLatch

    /**
     * @Description: *让一些线程阻塞直到另一些线程完成一系列操作后才被唤醒。
     * <p>
     * CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,这些线程会阻塞。
     * 其它线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞),
     * 当计数器的值变为0时,因await方法阻塞的线程会被唤醒,继续执行。
     * <p>
     * 解释:6个同学陆续离开教室后值班同学才可以关门。
     * <p>
     * main主线程必须要等前面6个线程完成全部工作后,自己才能开干
     */
    public class CountDownLatchDemo {
    
        public static void main(String[] args) throws InterruptedException {
            CountDownLatch countDownLatch = new CountDownLatch(6);
            for (int i = 1; i <= 6; i++) //6个上自习的同学,各自离开教室的时间不一致
            {
                new Thread(() -> {
                    System.out.println(Thread.currentThread().getName() + "	 号同学离开教室");
                    countDownLatch.countDown();
                }, String.valueOf(i)).start();
            }
            countDownLatch.await();
            System.out.println(Thread.currentThread().getName() + "	****** 班长关门走人,main线程是班长");
        }
    
    
    }
    

    1.1.2 CyclicBarrier

    /**
     * CyclicBarrier
     * 的字面意思是可循环(Cyclic)使用的屏障(Barrier)。它要做的事情是,
     * 让一组线程到达一个屏障(也可以叫同步点)时被阻塞,
     * 直到最后一个线程到达屏障时,屏障才会开门,所有
     * 被屏障拦截的线程才会继续干活。
     * 线程进入屏障通过CyclicBarrier的await()方法。
     * <p>
     * 集齐7颗龙珠就可以召唤神龙
     */
    public class CyclicBarrierDemo {
    
        public static void main(String[] args) {
            //CyclicBarrier(int parties, Runnable barrierAction)
            CyclicBarrier cyclicBarrier = new CyclicBarrier( 7, () -> { System.out.println("*****集齐7颗龙珠就可以召唤神龙"); });
    
            for (int i = 1; i <= 7; i++) {
                new Thread(() -> {
                    try {
                        System.out.println(Thread.currentThread().getName() + "	 星龙珠被收集 ");
                        cyclicBarrier.await();
                    } catch (InterruptedException | BrokenBarrierException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }, String.valueOf(i)).start();
            }
        }
    }
    

    突然又想到一个知识点(跑题中。。)wait 、await、sleep、notify、signal的区别:
    wait----sleep

    • 同:
      都是线程同步时会用到的方法,使当前线程暂停运行,把运行机会交给其它线程。
      如果任何线程在等待期间被中断都会抛出InterruptedException
      都是native方法
    • 异:
      所在类不同,wait()是Object超类中的方法;而sleep()是线程Thread类中的方法
      关键点是对锁的保持不同,wait会释放锁;而sleep()并不释放锁
      唤醒方法不完全相同,wait依靠notify或者notifyAll、中断发生、或者到达指定时间来唤醒;而sleep()则是到达指定的时间后被唤醒。
      使用的位置不同,wait只能用在同步代码块中,而sleep用在任何位置。
      wait----await
      这两个长得很像。await()的实现比较复杂:
    public final void await() throws InterruptedException {
                if (Thread.interrupted())
                    throw new InterruptedException();
                Node node = addConditionWaiter();
                int savedState = fullyRelease(node);
                int interruptMode = 0;
                while (!isOnSyncQueue(node)) {
                    LockSupport.park(this);
                    if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                        break;
                }
                if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                    interruptMode = REINTERRUPT;
                if (node.nextWaiter != null) // clean up if cancelled
                    unlinkCancelledWaiters();
                if (interruptMode != 0)
                    reportInterruptAfterWait(interruptMode);
            }
    

    先说下来源,await是ConditionObject类里面的方法,ConditionObject实现了Condition接口;而ReentrantLock里面默认有实现newCondition()方法,新建一个条件对象。该方法就是用在ReentrantLock中根据条件来设置等待。唤醒方法也是由专门的Signal()或者Signal()来执行。另外await会导致当前线程被阻塞,会放弃锁,这点和wait是一样的。

    由于所在的超类不同使用场景也不同,wait一般用于Synchronized中,而await只能用于ReentrantLock锁中.
    notify----signal
    notify使用来唤醒使用wait的线程;而signal是用来唤醒await线程。

    1.1.3 Semaphore

    /**

    • @Description: TODO(这里用一句话描述这个类的作用)

    • 在信号量上我们定义两种操作:

    • acquire(获取) 当一个线程调用acquire操作时,它要么通过成功获取信号量(信号量减1),

    • 要么一直等下去,直到有线程释放信号量,或超时。

    • release(释放)实际上会将信号量的值加1,然后唤醒等待的线程。

    • 信号量主要用于两个目的,一个是用于多个共享资源的互斥使用,另一个用于并发线程数的控制。
      */
      public class SemaphoreDemo {
      public static void main(String[] args) {
      Semaphore semaphore = new Semaphore(3);//模拟3个停车位

       for (int i = 1; i <= 6; i++) //模拟6部汽车
       {
           new Thread(() -> {
               try {
                   semaphore.acquire();
                   System.out.println(Thread.currentThread().getName() + "	 抢到了车位");
                   TimeUnit.SECONDS.sleep(new Random().nextInt(5));
                   System.out.println(Thread.currentThread().getName() + "	 ----离开了车位");
               } catch (InterruptedException e) {
                   e.printStackTrace();
               } finally {
                   semaphore.release();
               }
           }, String.valueOf(i)).start();
       }
      

      }
      }

  • 相关阅读:
    java后台设计简单的json数据接口,设置可跨域访问,前端ajax获取json数据
    java 多线程研究:锁的概念
    PHP 学习笔记之一:thinkPHP的volist标签
    Flask 学习篇二:学习Flask过程中的记录
    Docker 学习应用篇之三: Docker的简单实用
    CodeForces 832B Petya and Exam
    CodeForce 832A Sasha and Sticks
    Docker 学习应用篇之二: Docker的介绍和安装
    ASP.NET中AJAX的异步加载(Demo演示)
    Java实现 蓝桥杯VIP 算法训练 连通分块(并查集)
  • 原文地址:https://www.cnblogs.com/xhj928675426/p/13537450.html
Copyright © 2011-2022 走看看