Java面试进阶:Java并发包提供了哪些并发工具类?

标签: java&JVM  java  多线程  面试

java.util.concurrent 及其子包,集中了 Java 并发的各种基础工具类,具体主要包括几个方面:

1)提供了比 synchronized 更加高级的各种同步结构,包括 CountDownLatch、CyclicBarrier、Semaphore 等,可以实现更加丰富的多线程操作,比如利用 Semaphore 作为资源控制器,限制同时进行工作的线程数量。

2)各种线程安全的容器,比如最常见的 ConcurrentHashMap、有序的 ConcurrentSkipListMap,或者通过类似快照机制,实现线程安全的动态数组 CopyOnWriteArrayList 等。各种并发队列实现,如各种 BlockingQueue 实现,比较典型的 ArrayBlockingQueue、 SynchronousQueue 或针对特定场景的 PriorityBlockingQueue 等。

3)强大的 Executor 框架,可以创建各种不同类型的线程池,调度任务运行等,绝大部分情况下,不再需要自己从头实现线程池和任务调度器。

 

1、

CountDownLatch,允许一个或多个线程等待某些操作完成。

CyclicBarrier,一种辅助性的同步结构,允许多个线程等待到达某个屏障。

Semaphore,Java 版本的信号量实现。: Semaphore 就是个计数器,其基本逻辑基于 acquire/release,并没有太复杂的同步逻辑。

CountDownLatch 是不可以重置的,所以无法重用;而 CyclicBarrier 则没有这种限制,可以重用。

CountDownLatch 的基本操作组合是 countDown/await。调用 await 的线程阻塞等待 countDown 足够的次数,不管你是在一个线程还是多个线程里 countDown,只要次数足够即可。所以就像 Brain Goetz 说过的,CountDownLatch 操作的是事件。CyclicBarrier 的基本操作组合,则就是 await,当所有的伙伴(parties)都调用了 await,才会继续进行任务,并自动进行重置。注意,正常情况下,CyclicBarrier 的重置都是自动发生的,如果我们调用 reset 方法,但还有线程在等待,就会导致等待线程被打扰,抛出 BrokenBarrierException 异常。CyclicBarrier 侧重点是线程,而不是调用事件,它的典型应用场景是用来等待并发线程结束。

上一段CountDownLatch工作中的应用:两个数据源开两个线程,等待都结束后进行数据汇总返回前端报表展示

public class DataCenterServiceImpl implements DataCenterService {

    // 其他代码

    public CalculateIndicatorsKD getSemSummary(Date fromDate, Date toDate, String siteIdStr) throws Exception {

        SiteDataSqlSem request = new SiteDataSqlSem(fromDate, toDate);
        CountDownLatch countDownLatch = new CountDownLatch(2);
        ConcurrentHashMap<String, CalculateIndicatorsKD> datas = new ConcurrentHashMap<>();

        new Thread(() -> {
            //展现量presentCount、点击量clickCount、现金消费cashAmount
            CalculateIndicatorsKD semDatabaseSummary = deliverToolStatisticsDao.getSemSummary(siteIdStr, request.getFromDateStr(), request.getToDateStr());
            if (semDatabaseSummary == null) semDatabaseSummary = new CalculateIndicatorsKD();
            datas.put("database", semDatabaseSummary);
            countDownLatch.countDown();
        }).start();

        new Thread(() -> {
            //签约金额);sign_price,资源总量);clue_count,资源有效);resource_status
            CalculateIndicatorsKD semCrmSummary = crmDao.getSemSummary(fromDate, toDate, siteIdStr);
            if (semCrmSummary == null) semCrmSummary = new CalculateIndicatorsKD();
            datas.put("crm", semCrmSummary);
            countDownLatch.countDown();
        }).start();

        countDownLatch.await(60, TimeUnit.SECONDS);

        //展现量presentCount、点击量clickCount、现金消费cashAmount
        CalculateIndicatorsKD semDatabaseSummary = datas.get("database");
        if (semDatabaseSummary == null) semDatabaseSummary = new CalculateIndicatorsKD();

        //签约金额);sign_price,资源总量);clue_count,资源有效);resource_status
        CalculateIndicatorsKD semCrmSummary = datas.get("crm");
        if (semCrmSummary != null) {
            semDatabaseSummary.setQianYueJinE(semCrmSummary.getQianYueJinE());
            semDatabaseSummary.setZiYuanZongLiang(semCrmSummary.getZiYuanZongLiang());
            semDatabaseSummary.setZiYuanYouXiao(semCrmSummary.getZiYuanYouXiao());
        }

        return semDatabaseSummary;
    }

    // 其他代码
}

假设有 10 个人排队,我们将其分成 5 个人一批,通过 CountDownLatch 来协调批次:


import java.util.concurrent.CountDownLatch;
public class LatchSample {
  public static void main(String[] args) throws InterruptedException {
      CountDownLatch latch = new CountDownLatch(6);
           for (int i = 0; i < 5; i++) {
                Thread t = new Thread(new FirstBatchWorker(latch));
                t.start();
      }
      for (int i = 0; i < 5; i++) {
              Thread t = new Thread(new SecondBatchWorker(latch));
              t.start();
      }
           // 注意这里也是演示目的的逻辑,并不是推荐的协调方式
      while ( latch.getCount() != 1 ){
              Thread.sleep(100L);
      }
      System.out.println("Wait for first batch finish");
      latch.countDown();
  }
}
class FirstBatchWorker implements Runnable {
  private CountDownLatch latch;
  public FirstBatchWorker(CountDownLatch latch) {
      this.latch = latch;
  }
  @Override
  public void run() {
          System.out.println("First batch executed!");
          latch.countDown();
  }
}
class SecondBatchWorker implements Runnable {
  private CountDownLatch latch;
  public SecondBatchWorker(CountDownLatch latch) {
      this.latch = latch;
  }
  @Override
  public void run() {
      try {
          latch.await();
          System.out.println("Second batch executed!");
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
  }
}

后一批次的线程进行 await,等待前一批 countDown 足够多次。这个例子也从侧面体现出了它的局限性,虽然它也能够支持 10 个人排队的情况,但是因为不能重用

2、

 Map 放入或者获取的速度,而不在乎顺序,大多推荐使用 ConcurrentHashMap,反之则使用 ConcurrentSkipListMap;没有 ConcurrentTreeMap是因为线程安全并且红黑树平衡太困难,用ConcurrentSkipListMap替代

 

CopyOnWriteArraySet 是通过包装了 CopyOnWriteArrayList 来实现,CopyOnWrite的意思是任何修改操作都会拷贝原数组,修改后替换原来的数组

版权声明:本文为qililong88原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qililong88/article/details/105445959

智能推荐

TYVJ 4864 天天去哪吃 || 清北学堂金秋杯大奖赛

题目描述: 记录一下i这个值上次出现的位置在哪里,就是pre...

java反编译

jvm 把Boolean类型的值flag当做int类型处理。​​​ Foo.java: 由 class 文件生成 jasm 文件:java -jar asmtools.jar jdis Foo.class > Foo.jasm  修改jasm文件: 执行反编译: java -jar jd-gui-1.6.6.jar File 打开Foo.class文件:b修改为2 重新执行java...

【学习笔记】03-v-html的学习和示例

v-html的认识和使用 示例: 显示结果: 注意:v-html是有复制的...

Java实现在线考试系统(系统介绍)

1.和现在有的考试系统有以下几种优势: a.和现在有的系统比较起来,本系统有科目、章节、老师、学生、班级等信息的管理,还有批阅试卷查看已批阅试卷等。传统的考试系统划分并不细,业务功能简单。 b.和学校的考试系统还有外面的考试系统比较起来,本系统是B/S结构,学校的考试系统一般为C/S结构,性能方面不如B/S结构,并且C/S接口需要安装客户端,客户端压力很大,我的系统只需要电脑具有浏览器,在同一局域...

计算机视觉--多视几何初步尝试

基础矩阵的原理 K和K’分别是两个相机的参数矩阵。p和p’是X在平面π的坐标表示。所以可以得出 具体计算过程 代码: #!/usr/bin/env python coding: utf-8 from PIL import Image from numpy import * from pylab import * import numpy as np from imp ...

猜你喜欢

java初学者怎么学习才可以快速入门

java初学者怎么学习才可以快速入门 一、了解JAVA 我们要知道:Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计语言。 Java之父:詹姆斯·高斯林 1.1 java的三个体系 Java SE(Java Platform Standard Edition)。Java SE 以前称为 J2SE。它允许开发和部署在桌面、服务器、嵌入式环境...

字段属性之主键&增删改查&自增长&唯一键约束

字段属性之主键&自增长&唯一键约束 主键 主键:primary key 主要的键 一张表中只有一个字段可以使用对应的键,用来唯一的约束该字段里面的数据,不能重复,这种称之为主键 一张表只能最多一个主键 增加主键 SQL操作中有多种方式增加主键大体分为三种 1.在创建表的时候直接在字段之后跟primary key关键字(主键本身不允许为空) 优点:非常直接:缺点:只能使用一个字段作为...

linux下 基于libmad的socket多用户mp3音频在线播放服务器

在众多大神的帮助下,这个在线播放流媒体服务器终于完成啦。。。。 这个mp3流媒体服务器设计的思路是,服务器程序server用多线程实现和多个客户端的通信(这是必然的),然后发送给客户端当前的音频列表公客户端选择,之后根据k客户端的选择给多个客户端传输相应mp3文件的数据,同时,客户端进行实时地音频解码并播放。 关于libmad开源mp3音频解码库的使用,见上一篇博客吧。。。。 在服务器程序这一端,...

Nginx

Nginx Nginx简介: Nginx是一个高性能的http和反向代理服务器,特点是有内存少,并发能力强,事实上Nginx的并发能力确实在同类型网页服务器中表现较好, Nginx用作web服务器:Nginx可以作为静态页面的web服务器,同时还支持CGI语言,但不支持java,java程序只能通过Tomcat配合完成。Nginx专为性能优化而开发,性能是其最重要的考量,实现上非常注重效率,能经受...

SpringCloud Alibaba - Sentinel入门案例(二)(流控规则 | 直接 / 关联 / 链路 / 快速失败 / Warm Up / 排队等待)

SpringCloud Alibaba - Sentinel入门案例(二)(流控规则 | 直接 / 关联 / 链路 / 快速失败 / Warm Up / 排队等待) 回溯 Sentinel 基本概念 正文 环境准备 流控规则介绍 简单介绍 对 阈值类型 / 单机阈值做 测试 流控模式 直接流控模式 关联流控模式 链路流控模式 资源名称的修改 链路模式正文 坑来了,怎么解决? 禁止收敛URL的入口 ...