高并发编程之面试题一
题目:实现一个容器,提供两个方法,add,size。写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,当个数到5个时,线程2给出提示并结束。
程序一,分析下面程序能否实现
List lists = new ArrayList();public void add(Object o) {lists.add(o);}public int size() {return lists.size();}public static void main(String[] args) {MyContainer1 c = new MyContainer1();new Thread(() -> { //线程一for (int i = 0; i < 10; i++) {c.add(new Object());System.out.println("add" + i);try {TimeUnit.SECONDS.sleep(1);} catch (Exception e) {e.printStackTrace();}}}, " t1").start();new Thread(() -> { //线程二while (true) {if (c.size() == 5) {break;}}System.out.println("t2线程结束");}, "t2").start();}
运行结果:线程1运行完成,正常打印。线程2一直在运行,未结束。
分析:lists对于线程2不可见,所以不能实时的访问到lists的size。
程序二 加volatile关键字
//添加volatile,使t2能够得到通知volatile List lists = new ArrayList();public void add(Object o){lists.add(o);}public int size(){return lists.size();}public static void main(String[] args) {MyContainer2 c = new MyContainer2();new Thread(()->{ //线程一for (int i = 0; i < 10; i++) {c.add(new Object());System.out.println("add " + i);try {TimeUnit.MILLISECONDS.sleep(10);} catch (Exception e) {e.printStackTrace();}}}," t1").start();new Thread(()->{ //线程二while (true) {if (c.size() == 5) {break;}}System.out.println("t2线程结束");}, "t2").start();}
运行结果:正常
分析:由于volatile关键字保证了lists对于线程2可见,所以当size发生变化后线程2能获取到lists的size值。
不足:线程2的死循环非常浪费cpu资源。
程序三 使用wait和notify实现
//添加volatile,使t2能够得到通知volatile List lists = new ArrayList();public void add(Object o) {lists.add(o);}public int size() {return lists.size();}public static void main(String[] args) {MyContainer4 c = new MyContainer4();Object lock = new Object();new Thread(() -> { //线程一synchronized (lock) {System.out.println("t2启动");if (c.size() != 5) {try {lock.wait();} catch (Exception e) {e.printStackTrace();}}System.out.println("t2结束");lock.notify();}}, " t2").start();new Thread(() -> { //线程二System.out.println("t1启动");synchronized (lock) {for (int i = 0; i < 10; i++) {c.add(new Object());System.out.println("add " + i);if (c.size() == 5) {lock.notify();// 释放锁,让t2得以执行try {lock.wait();} catch (Exception e) {e.printStackTrace();}}try {TimeUnit.SECONDS.sleep(1);} catch (Exception e) {e.printStackTrace();}}}}, "t1").start();}
这里使用wait和notify做到,wait会释放锁,而notify不会释放锁。需要注意的是运用这种方法,必须要保证t2先执行,也就是首先让t2监听才可以。
程序四 使用Latch(门闩)替代wait notify来进行通知
//添加volatile,使t2能够得到通知volatile List lists = new ArrayList();public void add(Object o) {lists.add(o);}public int size() {return lists.size();}public static void main(String[] args) {MyContainer5 c = new MyContainer5();Object lock = new Object();CountDownLatch latch = new CountDownLatch(1);new Thread(() -> { //线程一System.out.println("t2启动");if (c.size() != 5) {try {latch.await();// 也可以指定等待时间]//latch.await(5000, TimeUnit.MICROSECONDS);} catch (Exception e) {e.printStackTrace();}System.out.println("t2结束");}}, " t2").start();new Thread(() -> { //线程二System.out.println("t1启动");for (int i = 0; i < 10; i++) {c.add(new Object());System.out.println("add " + i);if (c.size() == 5) {// 打开门阀,让t2得以执行latch.countDown();}try {TimeUnit.SECONDS.sleep(1);} catch (Exception e) {e.printStackTrace();}}}, "t1").start();}
使用Latch(门闩)替代wait notify来进行通知 好处是通信方式简单,同时也可以指定等待时间 使用await和countdown方法替代wait和notify。
CountDownLatch不涉及锁定,当count的值为零时当前线程继续运行。 当不涉及同步,只是涉及线程通信的时候,用synchronized + wait/notify就显得太重了。这时应该考虑countdownlatch/cyclicbarrier/semaphore
读下面文章进行深入了解:
Java并发编程:CountDownLatch、CyclicBarrier和 Semaphore
高并发编程之面试题一相关推荐
- 高并发编程_高并发编程系列:7大并发容器详解(附面试题和企业编程指南)...
不知道从什么时候起,在Java编程中,经常听到Java集合类,同步容器.并发容器,高并发编程成为当下程序员需要去了解掌握的技术之一,那么他们有哪些具体分类,以及各自之间的区别和优劣呢? 只有把这些梳理 ...
- Java并发编程面试题(2020最新版)
转载自 Java并发编程面试题(2020最新版) 基础知识 并发编程的优缺点 为什么要使用并发编程(并发编程的优点) 充分利用多核CPU的计算能力:通过并发编程的形式可以将多核CPU的计算能力发挥到 ...
- libevent c++高并发网络编程_高并发编程学习(2)——线程通信详解
前序文章 高并发编程学习(1)--并发基础 - https://www.wmyskxz.com/2019/11/26/gao-bing-fa-bian-cheng-xue-xi-1-bing-fa-j ...
- java书籍_还搞不定Java多线程和并发编程面试题?你可能需要这一份书单!
点击蓝色"程序员书单"关注我哟 加个"星标",每天带你读好书! 在介绍本书单之前,我想先问一下各位读者,你们之前对于Java并发编程的了解有多少呢.经过了1 ...
- 【2022最新Java面试宝典】—— Java并发编程面试题(123道含答案)
目录 一.基础知识 1. 为什么要使用并发编程 2. 多线程应用场景 3. 并发编程有什么缺点 4. 并发编程三个必要因素是什么? 5. Java 程序中怎么保证多线程的运行安全? 6. 并行和并发有 ...
- 网络编程和并发编程面试题
网络编程和并发编程面试题 1.简述 OSI 七层协议. 一.应用层 与其它计算机进行通讯的一个应用,它是对应应用程序的通信服务的.例如,一个没有通信功能的字处理程序就不能执行通信的代码,从事字处理工作 ...
- Java JUC高并发编程(一)
目录 一.概述 二.Lock接口 三.线程间的通信 解决虚假唤醒问题 Lock通信示例: 四.线程间定制化通信 一.概述 JUC就是java.util.concurrent工具包的简称,这是一个处理线 ...
- 啃完阿里这份高并发编程核心笔记,反手涨了 5K
高并发编程 提到并发编程很多人就会头疼了:首先就是一些基础概念:并发,并行,同步,异步,临界区,阻塞,非阻塞还有各种锁全都砸你脸上,随之而来的就是要保证程序运行时关键数据在多线程中的可见性.核心业务的 ...
- 啃完阿里这份高并发编程核心笔记,反手涨了5K
高并发编程 提到并发编程很多人就会头疼了:首先就是一些基础概念:并发,并行,同步,异步,临界区,阻塞,非阻塞还有各种锁全都砸你脸上,随之而来的就是要保证程序运行时关键数据在多线程中的可见性.核心业务的 ...
- 高并发编程-重新认识Java内存模型(JMM)
文章目录 从CPU到内存模型 内存模型如何确保缓存一致性 并发变成需要解决的问题 (原子性.可见性.有序性) 内存模型需要解决的问题 Java内存模型 JMM的API实现 原子性 synchroniz ...
最新文章
- vim ctags使用方法
- 每天一个前端名词——Babel
- modify timezone
- MFC 直线 虚线 折线 圆 椭圆 矩形 弧形
- Android之jni编译报错comparsion between signed and unsigned integer expressions解决办法
- 视频光端机选型及常见品牌
- 支付宝兑换的扫地机器人_支付宝里这笔钱赶紧用掉!年底过期作废
- dubbo发布webservice服务
- vb使用open方法读写文件
- zip4j实现文件压缩与解压缩 common-compress压缩与解压缩
- paip.android 手机输入法制造大法
- (首个填坑)联想拯救者Y7000(自带win10 home) 安装Ubuntu16.04.6 + NVIDIA GTX1650驱动
- mysql英文版怎么调中文_navicat for mysql怎么设置中文
- 官方固件库V1.4版本介绍
- NoSQL--Redis
- Python ---------列表 集合 字典 深浅拷贝
- 微信多客服系统开发教程
- Hexo博客搭建教程
- python定时导出已发送文件_Python链接数据库查询导出查询结果到Excel并定时发送邮件到指定邮箱,实现巡检功能(亲测可用!!!)...
- CrossWalk - Android 动态加载so库文件