常见面试题06

简介: 本内容介绍了 BIO、NIO、AIO 三种 I/O 模型的区别与演进,涵盖阻塞与非阻塞处理机制、多路复用及异步回调原理。同时讲解了 Java IO 流的分类与用途,并深入解析 ThreadLocal 的实现机制与使用注意事项,最后对比了悲观锁与乐观锁的原理及适用场景。

说说 BIO、NIO、AIO

BIO(阻塞 I/O)

  • 是指 b. c. d.这几个阶段,线程都得阻塞,腾不出手干别的,即使此时它无所事事
  • 高并发下,阻塞线程多了,处理连接、处理请求的能力就会大受影响
  • 增加线程不可行,毕竟线程是有限资源,这是成本问题
  • 不增加线程也不行,没有新线程,没人去处理新连接,处理新请求

NIO(非阻塞 I/O)

  • 是指 b. c. 这两个阶段,线程可以不阻塞,腾出手干别的(怎么干别的,要靠多路复用)
  • 非阻塞 I/O 通常结合多路复用技术一起使用,能够在高并发下用少量线程处理大量请求
  • 多路复用是以面向事件的方式处理连接、处理请求,有事件发生才去处理,没有事件则不会占用线程
  • 使用了多路复用技术后,新客户端来了要连接,客户端发来了新请求,都会产生事件,把这些事件交给一个线程去统一处理就行了
  • 线程不会在高并发下存在无事可做的现象,它被充分压榨,利用率高

AIO(异步 I/O)

  • NIO 在 d. 这个阶段,线程仍需阻塞,不能被解放出来干其它活
  • AIO 则更进一步,只需要提前准备好回调函数,在数据复制时线程被解放,该干嘛干嘛,等数据复制完毕,由系统使用另外线程来调用回调函数做后续处理
  • AIO 在 Linux 下本质还是用多路复用技术来实现

IO流

  • 字节流,读写时以字节为单位,抽象父类是 InputStream 和 OutputStream
  • 字符流,读写时以字符为单位,抽象父类是 Reader 和 Writer
  • 转换流,用来把字节流转换为字符流,相关类:InputStreamReader 和 OutputStreamWriter
  • 缓冲流,增加缓冲来提高读写效率,相关类:
  • BufferedInputStream
  • BufferedOutputStream
  • BufferedReader
  • BufferedWriter
  • 对象流,配合序列化技术将 java 对象转换成字节流或逆操作,相关类:ObjectInputStream,ObjectOutputStream

ThreadLocal 的原理

ThreadLocal 的主要目的是用来实现多线程环境下的变量隔离

  • 【解释】即每个线程自己用自己的资源,这样就不会出现共享,没有共享,就不会有多线程竞争的问题

原理

  • 每个线程对象内部有一个 ThreadLocalMap,它用来存储这些需要线程隔离的资源
  • 资源的种类有很多,比如说数据库连接对象、比如说用来判断身份的用户对象 ...
  • 怎么区分它们呢,就是通过 ThreadLocal,它作为 ThreadLocalMap 的 key,而真正要线程隔离的资源作为 ThreadLocalMap 的 value
  • ThreadLocal.set 就是把 ThreadLocal 自己作为 key,隔离资源作为值,存入当前线程的 ThreadLocalMap
  • ThreadLocal.get 就是把 ThreadLocal 自己作为 key,到当前线程的 ThreadLocalMap 中去查找隔离资源
  • ThreadLocal 一定要记得用完之后调用 remove() 清空资源,避免内存泄漏

解释悲观锁与乐观锁

悲观锁

  • 像 synchronized,Lock 这些都属于悲观锁
  • 如果发生了竞争,失败的线程会进入阻塞
  • 【理解】悲观的名字由来:害怕其他线程来同时修改共享资源,因此用互斥锁让同一时刻只能有一个线程来占用共享资源

乐观锁

  • 像 AtomicInteger,AtomicReference 等原子类,这些都属于乐观锁
  • 如果发生了竞争,失败的线程不会阻塞,仍然会重试
  • 【理解】乐观的名字由来:不怕其他线程来同时修改共享资源,事实上它根本不加锁,所有线程都可以去修改共享资源,只不过并发时只有一个线程能成功,其它线程发现自己失败了,就去重试,直至成功

适用场景

  • 如果竞争少,能很快占有共享资源,适合使用乐观锁
  • 如果竞争多,线程对共享资源的独占时间长,适合使用悲观锁


目录
相关文章
|
开发工具 git
Gitlab/GitHub:迁移代码,并保留历史记录
Gitlab/GitHub:迁移代码,并保留历史记录
Gitlab/GitHub:迁移代码,并保留历史记录
|
6月前
|
存储 安全 Java
Java 集合面试题从数据结构到 HashMap 源码剖析详解及长尾考点梳理
本文深入解析Java集合框架,涵盖基础概念、常见集合类型及HashMap的底层数据结构与源码实现。从Collection、Map到Iterator接口,逐一剖析其特性与应用场景。重点解读HashMap在JDK1.7与1.8中的数据结构演变,包括数组+链表+红黑树优化,以及put方法和扩容机制的实现细节。结合订单管理与用户权限管理等实际案例,展示集合框架的应用价值,助你全面掌握相关知识,轻松应对面试与开发需求。
353 3
|
9月前
|
负载均衡 Java Nacos
Spring Cloud五大组件
Spring Cloud五大组件
|
6月前
|
人工智能 Java 数据库
如何保证接口幂等性?
在分布式系统中,接口幂等性至关重要。本文详解其定义、重要性及实现方案,包括唯一索引、Token机制、分布式锁、状态机与版本号机制,并提供最佳实践建议,助你提升系统可靠性与用户体验。
1098 1
|
JSON Dart 算法
Dart/Flutter工具模块:the_utils
Dart/Flutter工具模块:the_utils
223 0
|
XML Java 程序员
Java的基础入门(1)
Java的基础入门
266 7
|
Java 开发者 Spring
深入理解Spring Boot中的自动配置原理
深入理解Spring Boot中的自动配置原理
2215 1
|
开发框架 Java 开发者
Spring Boot中的自动装配原理
Spring Boot中的自动装配原理
3199 1
|
前端开发 Java 开发者
深入理解 Spring Boot 注解:核心功能与高级用法详解
深入理解 Spring Boot 注解:核心功能与高级用法详解
1673 1
|
存储 缓存 数据库
接口幂等有哪些实现方式
接口幂等有哪些实现方式
491 0