• Semaphroe + CountDown


    Semaphore

    基本使用

    synchronized 可以起到锁的作用,但某个时间段内,只能有一个线程允许执行

    Semaphore(信号量)用来限制能同时访问共享资源的线程上限(不是资源数),非重入锁

    不像之前的reentrantlock那些是独占锁。Semaphore是共享资源有多个,允许多个线程占有,只是希望对数量进行把控

    构造方法:

    • public Semaphore(int permits):permits 表示许可线程的数量(state)

    • public Semaphore(int permits, boolean fair):fair 表示公平性,如果设为 true,下次执行的线程会是等待最久的线程

    常用API:

    • public void acquire():表示获取许可

    • public void release():表示释放许可,acquire() 和 release() 方法之间的代码为同步代码

     public static void main(String[] args) {
         // 1.创建Semaphore对象
         Semaphore semaphore = new Semaphore(3);
     ​
         // 2. 10个线程同时运行
         for (int i = 0; i < 10; i++) {
             new Thread(() -> {
                 try {
                     // 3. 获取许可
                     semaphore.acquire();
                     sout(Thread.currentThread().getName() + " running...");
                     Thread.sleep(1000);
                     sout(Thread.currentThread().getName() + " end...");
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 } finally {
                     // 4. 释放许可
                     semaphore.release();
                 }
             }).start();
         }
     }


    应用

    线程数等于资源数就很合适

    • 单机版限流,仅仅限制线程数,不是限制资源数。

    • 简单连接池。对比享元模式的wait、notify。性能和可读性更好

    CountDown

    倒计时锁

    为什么不用join

    • join也可以使主线程等待3个线程结束再执行。

    • join属于比较底层的api用起来比较繁琐,比如将来肯定是使用线程池,线程都是不断再运行的,肯定不能让某一个线程结束。

    基本使用

    CountDownLatch:计数器,用来进行线程同步协作,等待所有线程完成倒计时计时

    构造器:

    • public CountDownLatch(int count):初始化唤醒需要的 down 几步

    常用API:

    • public void await():让当前线程等待,必须 down 完初始化的数字才可以被唤醒,否则进入无限等待【计时(数)器走完】

    • public void countDown():计数器进行减 1(down 1)

    应用:同步等待多个 Rest 远程调用结束

     // LOL 10人进入游戏倒计时
     public static void main(String[] args) throws InterruptedException {
         CountDownLatch latch = new CountDownLatch(10);
         ExecutorService service = Executors.newFixedThreadPool(10);
         String[] all = new String[10];
         Random random = new Random();
     ​
         for (int j = 0; j < 10; j++) {
             int finalJ = j;//常量
             service.submit(() -> {
                 for (int i = 0; i <= 100; i++) {
                     Thread.sleep(random.nextInt(100));  //随机休眠
                     all[finalJ] = i + "%";
                     System.out.print("\r" + Arrays.toString(all));  // \r代表覆盖
                 }
                 latch.countDown();
             });
         }
         latch.await();
         System.out.println("\n游戏开始");
         service.shutdown();
     }
     /*
     [100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%]
     游戏开始
  • 相关阅读:
    从 iOS 设备恢复数据的 20 个iOS 数据恢复工具
    Liunx上JSON处理工具jq
    Python手册
    java并发之AQS详解(待更)
    [CSP-S 2022] 策略游戏
    深度学习OCR中文识别 - opencv python 计算机竞赛
    【移远QuecPython】EC800M物联网开发板的硬件PWM和PWM输出BUG
    Servlet
    WOODWARD 5466-318 是否打算转向开放的工业以太网协议
    Ruoyi表单构建
  • 原文地址:https://blog.csdn.net/2301_79437276/article/details/139842521