【Java基础】day11

news2025/1/11 4:11:41

day11

一、BIO、NIO、AIO 三种 IO 模型分别是什么?

BIO (Blocking I/O)同步阻塞的 I/O 、NIO(New/Non-blocking I/O) 同步非阻塞的 I/O 、AIO(Asynchronous I/O) 异步非阻塞的 I/O 。这三种 IO 模型是 Java 中提供的 API ,与系统 IO 是不相同的。在Linux(UNIX)操作系统中,共有五种 IO 模型,分别是:阻塞IO模型非阻塞IO模型IO复用模型信号驱动IO模型以及异步IO模型

  • 阻塞:发起一个请求之后,请求方如果没有等待到请求的结果,会一直处于等待,线程会被挂起,无法从事其他任务,条件就绪才能继续执行
  • 非阻塞:发起一个请求之后,请求方不必等待到请求的结果,可以去执行其他任务
  • 同步:发起一个调用之后,被调用者未处理完成之前,调用不返回
  • 异步:发起一个调用之后,立刻得到被调用者的确认表示接收到调用,此时被调用者还没有返回结果,此时我们可以继续处理其他请求,被调用者处理完成之后通过事件、回调等机制来通知调用者

202205271637743.png
采用 BIO 的服务端,通常由一个独立的 Acceptor 线程来监听客户端的连接。通常是使用 while(true) 循环与 accept() 方法来让线程监听请求。一个线程在处理请求的时候是不能接收到来自其他用户的连接请求的,但是可以通过多线程的方式来让服务端能够同时服务多个用户。这个模型是典型的一请求一应答的通信模型。
采用 NIO 的服务端,引入了新的 Selector 、 Buffer 以及 Channel 概念。相比于 BIO 模型,NIO 不使用传统的 Socket 和 ServerSocket 类,而是使用对应的 SocketChannel 和 ServerSocketChannel 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞模式。

  1. NIO 是非阻塞的,IO 是阻塞的。因为 NIO 使用的是 Buffer 对象,读写的时候只需要开始即可,等待读取的过程中可以继续处理其他任务;IO 则要一直等待读/写完成才能继续其他任务。
  2. NIO 使用 Channel 进行通信,IO 使用 Stream 流进行通信。 NIO 是使用 Channel 通信,在 Channel 中对 Buffer 对象进行读写操作,可以支持双向读写和异步操作;而 Stream 只支持单向读写操作。
  3. Selector 选择器,NIO 模型中引入了 Selector 以及 Channel 概念。通过 Selector ,可以让单线程处理多个 Channel ,这样的处理可以提高线程的利用率。

JDK 中对于 NIO 的实现比较复杂,且还有空轮询的弊端,自行实现的 NIO 比较容易出现问题。通常使用的 Netty 框架的 NIO 模型来进行开发。

采用 AIO 的服务端,是异步非阻塞的。表示在发出请求之后,调用者可以继续执行其他任务,被调用者完成请求任务之后,相应的线程可以立即感知到(通常是操作系统发出通知)并且可以当即处理。目前 AIO 的应用比较少,适用于连接数目多且连接比较长的架构。

参考文档:
Java面试常考的 BIO,NIO,AIO 总结_小树的博客-CSDN博客
Java NIO浅析 - 知乎 (zhihu.com)
漫话:如何给女朋友解释什么是Linux的五种IO模型? (qq.com)

二、Java 中的内存分配策略有哪些?

Java 中的内存分配策略主要有两种,分别是指针碰撞和空闲列表。

指针碰撞:假设 Java 堆中的内存都是规整的,所有被使用过的放在一边,未使用过的放在一边,中间有一个指针作为分界,分配内存仅仅需要把这个指针向空闲空间方向移动一段即可。

空闲列表:如果 Java 堆中的内存不是规整的,已使用过的和空闲的交错,虚拟机就需要维护一个列表,记录哪些内存是可用的,在分配的时候找到一块足够大的内存进行分配。

三、ThreadLocal 线程变量是什么?

ThreadLocal 又被叫做本地线程变量,意味着 ThreadLocal 中填充的变量只属于当前线程,对于其他线程来说是隔离的。 ThreadLocal 为每个线程都创建了一个副本用来保存各自的变量,这样的设计下,线程各自对应的变量是其他线程不可访问的,这样就形成了隔离的环境。

  • 每个副本中的变量只能由当前 Thread 访问,别的线程是访问不到的。所以在开发的时候要注意变量是否需要被移除,否则容易造成内存占用且不易回收。
  • ThreadLocal 为每个线程都创建了各自的副本,且线程之间彼此隔离,这样就不存在多线程下的线程安全问题了。
  • ThreadLocal 由于采用的线程之间隔离的方式,可以用于传递参数。实例需要在多个方法中共享,但不希望被多线程共享。比如在 Spring 中的 request 和 session 就使用了 ThreadLocal 变量来实现。

使用 ThreadLocal 的时候,通常需要实现其中的三个方法:getsetremove

@Component
public class HostHolder {
    private final ThreadLocal<User> users = new ThreadLocal<>();

    public void setUser(User user) {
        users.set(user);
    }
    public User getUser() {
        return users.get();
    }
    public void removeUser() {
        users.remove();
    }
}

以上的代码实现了将用户保存至各自对应的 ThreadLocal 中,可以比较容易地实现保存用户状态。

在 ThreadLocal 中一共存在四个方法,分为是 initialValue()set()get()remove()。ThreadLocal 底层为了实现线程之间的隔离,使用 Map 来存储每个线程对应的副本,key 对应的是每个线程的线程 ID ,value 值为对应的副本空间中存放的变量。
202205271637338.png
ThreadLocal 的组成结构:
202205271637948.png
Thread 类中存在一个属性名为 threadLocals ,归属于 ThreadLocalMap 类,内部存在 Entry 数组,类似于 Map 。 Entry 数组中,key 存放的是 ThreadLocal 类,value 存放的是我们需要存放的对象。主要结构为:
f3f029c7ad43dc2d5541465a887d4e13.png

static class ThreadLocalMap {

    /**
     * The entries in this hash map extend WeakReference, using
     * its main ref field as the key (which is always a
     * ThreadLocal object).  Note that null keys (i.e. entry.get()
     * == null) mean that the key is no longer referenced, so the
     * entry can be expunged from table.  Such entries are referred to
     * as "stale entries" in the code that follows.
     */
    static class Entry extends WeakReference<ThreadLocal<?>> {
        /** The value associated with this ThreadLocal. */
        Object value;

        Entry(ThreadLocal<?> k, Object v) {
            super(k);
            value = v;
        }
    }
}

由于 Entry 继承自 WeakReference 弱引用类,弱引用的特点是只能存在于下一次 GC 之前,发生 minorGC 或 majorGC 就会被回收,造成 key 变为空,value 还会被栈使用,也就造成了内存泄露问题。
08f2c8da5f8549b58f902c887ef28b3b.png
如果没有对 ThreadLocal 中的变量进行删除或者替换,它的生命周期将会与线程同步;如果线程又交给线程池进行管理实现线程复用,核心线程的生命周期将会变得不可预测,不可避免地导致 ThreadLocal 中变量的生命周期也持续延长那个,导致内存泄漏的问题越来越严重。

  • 可以自己调用 remove 方法将不要的数据移除避免内存泄漏的问题
  • 每次在做set方法的时候会清除之前 key 为 null
  • 使用反射机制获取当前线程对应的 ThreadLocalMap ,手动移除

参考文档:
史上最全ThreadLocal 详解_fu_bobo-CSDN博客_threadlocal
并发编程-Threadlocal - 简书 (jianshu.com)
源码篇:ThreadLocal的奇思妙想

四、 Redis 的缓存过期策略有哪些?

Redis 会把设置了过期时间的 key 放入一个独立的字典里,在 key 过期时并不会立刻删除它。 Redis 会通过如下两种策略,来删除过期的 Key 。

定时过期:每个设置过期时间的 key 都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好。但是会占用大量的 CPU 资源去处理过期的数据,影响缓存的响应时间和吞吐量。

惰性过期:只有当访问一个 key 时,才会判断该 key 是否已过期,过期则清除。该策略可以最大化节省 CPU 资源,但是很消耗内存,许多的过期数据都还存在内存中。极端情况可能出现大量的过期 key 没有再次被访问,但是不会被清除,占用大量内存。

定期过期:每隔一定的时间,会扫描一定数量的数据库的 expires 字典中一定数量的 key(是随机的),并且清除其中已过期的 key。该策略是定时过期和惰性过期的折中方案。通过设置定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得 CPU 和内存资源达到最优的平衡效果。

Redis 默认每秒执行 10 次过期扫描(配置 hz 选项),扫描策略如下:从过期字典中随机选择 20 个 key ,删除这 20 个 key 中 已过期的 key ;如果过期的 key 的比例超过 25% ,则再从过期字典中随机选择 20 个 key 。

分桶策略:定时过期的优化,将过期时间点相近的 key 放在⼀起,按时间扫描分桶。

参考资料:
缓存过期都有哪些策略?_图图是个好孩纸~的博客-CSDN博客_缓存过期策略

五、 Redis 的缓存淘汰策略有哪些?

当 Redis 占用内存超出最大限制 maxmemory 时,可采用最大内存策略 maxmemory-policy,让 Redis 淘汰一些数据,以腾出空间继续提供服务。

  • noeviction:对可能导致增大内存的命令返回错误(大多数写命令, DEL 除外)
  • volatile-ttl:在设置了过期时间的 key 中,选择剩余寿命 TTL 最短的 key ,将其淘汰
  • volatile-lru:在设置了过期时间的 key 中,选择最少使用的 key (LRU) ,将其淘汰
  • volatile- random:在设置了过期时间的 key 中,随机选择一些key,将其淘汰
  • allkeys-lru:在所有的 key 中,选择最少使用的 key (LRU) ,将其淘汰
  • allkeys-random:在所有的 key 中,随机选择一些 key ,将其淘汰

Redis 中的 LRU 算法逻辑和普通的 LRU 略有区别。

  • 普通的 LRU 需要维护一个链表,按照访问顺序存储数据。新的被访问的数据存储到表头,最近访问的 Key 在表头,最少访问的数据放在链表尾部。
  • Redis 使用的 LRU 是一种近似 LRU 算法。给每个 Key 维护一个时间戳,淘汰时随机取样五个值,从中淘汰掉最旧的 Key 。这个时间戳的更新就是根据数据被访问的时间来进行记录的,这种方式相比于传统的 LRU 更加节省内存,也提高了计算的效率,且可以取得和 LRU 近似的淘汰效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/118365.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

前端例程20221227:下雪动画

演示 动图太大了不好上传&#xff0c;这里就放个静态图吧&#xff0c;实际上这里是雪花从上到下飘落的效果。 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content&quo…

【Spring【AOP】】——20、搭建一个AOP测试环境?

&#x1f4eb;作者简介&#xff1a;zhz小白 公众号&#xff1a;小白的Java进阶之路 专业技能&#xff1a; 1、Java基础&#xff0c;并精通多线程的开发&#xff0c;熟悉JVM原理 2、熟悉Java基础&#xff0c;并精通多线程的开发&#xff0c;熟悉JVM原理&#xff0c;具备⼀定的线…

Linux系统运行时参数命令--CPU性能监控

目录 2 CPU性能监控 2.1 平均负载和CPU使用率 1 平均负载基础 2 使用uptime命令分析平均负载 3 平均负载与 CPU 使用率 4 CPU使用率监测命令 ps查找进程信息 top命令查询进程的cpu、内存信息 mpstat pidstat 场景一&#xff1a;CPU 密集型进程 场景二&#xff1a;I…

嵌入式开发学习之--DMA(上)

提示&#xff1a;本篇文章主要了解学习一下DMA 文章目录前言一、DMA是什么&#xff1f;二、DMA使用步骤1、外设通道选择2.2、仲裁器2.3、FIFO2.4、存储器端口 外设端口2.5、编程端口三、DMA结构体初始化详解总结前言 上一篇文章学习了串口通信&#xff0c;这一篇我们来学习一下…

虹科案例 | 实现了新的核磁共振应用!(下)

摘要 光纤传感器已成为推动MRI最新功能套件升级和新MRI设备设计背后的关键技术。在这篇文章中&#xff0c;我们介绍了三个基于MRI的运动控制应用&#xff0c;展示了最近开发的、可在市场上买到的基于MRI的安全光纤反馈传感器的操作和使用。 案例研究 案例研究#1用于验证MRI技…

【聆思CSK6 视觉AI开发套件试用】体验AI功能

本篇文章来自极术社区与聆思科技组织的CSK6 视觉AI开发套件活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;YiCheng 很高兴极术社区和聆思科技举办的开发板申请试用活动&#xff0c;放张开箱图&#xff1a; 开发板介绍NanoKit开发板# NanoKit开发板是…

【算法】前缀和与差分

文章目录1.一维前缀和输入格式输出格式数据范围2.二维前缀和输入格式输出格式数据范围3.一维差分输入格式输出格式数据范围4.二维差分输入格式输出格式数据范围前缀和差分是一对逆运算1.一维前缀和 有一个长度为n的数组an:a1,a2…an; 对于前缀和&#xff1a;Si a1a2…ai 如何…

刷爆力扣之二进制求和

刷爆力扣之二进制求和 HELLO&#xff0c;各位看官大大好&#xff0c;我是阿呆 &#x1f648;&#x1f648;&#x1f648; 今天阿呆继续记录下力扣刷题过程&#xff0c;收录在专栏算法中 &#x1f61c;&#x1f61c;&#x1f61c; 该专栏按照不同类别标签进行刷题&#xff0c;…

Spark零基础入门实战(八)Spark运行时架构

Spark有多种运行模式,可以运行在一台机器上,称为本地(单机)模式,也可以以YARN或Mesos作为底层资源调度系统以分布式的方式在集群中运行,称为Spark On YARN模式,还可以使用Spark自带的资源调度系统,称为Spark Standalone模式。 本地模式通过多线程模拟分布式计算,通常…

如何使用Python创建一个虚拟助理

使用Python创建一个虚拟助手 虚拟助理是基于人工智能的程序。它们是一种智能计算机程序&#xff0c;可以通过语音命令或文本理解人类的自然语言&#xff0c;并为用户执行任务。本文将指导你通过使用Python库来创建你自己的语音助手的过程。 在本教程中&#xff0c;我将在Jetb…

2022已经到了尾声,做一个漂亮的倒计时页面迎接2023年的到来

个人主页&#xff1a;天寒雨落的博客_CSDN博客-初学者入门C语言,python,数据库领域博主 目录 前言 效果图 网页直链 完整代码 倒计时的实现原理 前言 2022即将到来&#xff0c;快来一起做一个元旦倒计时分享给自己喜欢的人吧~ 效果图 网页直链 下面是可以直接访问的网页…

离散数学实践三判别图的连通性【JAVA实现】

文章目录思路重要算法&Warshall 算法代码全部代码效果展示思路 对于给定的邻接矩阵 A&#xff0c;可以用可达矩阵 Warshall 算法求出 A 所表示的图的可达矩阵 P。 对于可达矩阵 P 来说&#xff0c;如果 P 的所有元素均为 111&#xff0c;则所给的有向图是强连通的&#xf…

Python实现的一个简洁轻快的后台管理框架.支持拥有多用户组的RBAC管理后台,不用配置各种运行环境

Mini Admin 完整代码下载地址&#xff1a;Python实现的一个简洁轻快的后台管理框架.支持拥有多用户组的RBAC管理后台 Mini Admin,一个简洁轻快的后台管理框架.支持拥有多用户组的RBAC管理后台 &#x1f680; 应用场景&#xff1a;2-5人的管理团队&#xff0c;需要管理的资源数…

Mysql 慢日志处理

勿以恶小而为之&#xff0c;勿以善小而不为---- 刘备 有时候我们需要排查执行缓慢的SQL语句&#xff0c;这就用到了mysql慢查询日志。 开启慢查询日志的方式有两种&#xff1a;临时开启和永久开启。 开启慢查询日志功能可能需要mysql的版本达到5.7 查看版本号 select VERSI…

linux常用命令-路径切换及查看

切换路径-cd 我们可以使用cd&#xff08;change directory&#xff0c;切换目录&#xff09;的命令来进行目录切换 常规 其命令格式为 cd [相对路径或绝对路径] 例如&#xff1a; // 使用相对路径&#xff0c;切换到postfix目录下 cd ../postfix// 使用绝对路径切换到/var/…

centos7安装zabbix5.0

zabbix官网&#xff1a;https://www.zabbix.com/ 安装Zabbix存储库 rpm -Uvh https://repo.zabbix.com/zabbix/5.0/rhel/7/x86_64/zabbix-release-5.0-1.el7.noarch.rpm yum clean all安装Zabbix server&#xff0c;Web前端&#xff0c;agent yum install zabbix-server-mys…

2023年天津农学院专升本专业课考试考场安排与东西校区入校须知

天津农学院2023年高职升本科专业课考试考场安排等事宜的通知一、考试时间及考场分布情况天津农学院专升本专业课考试2022年12月31日上午在天津农学院东、西校区进行&#xff0c;每位考生请按照准考证上标注的地点参加考试即可&#xff0c;考场安排及考场分布图详见。天津农学院…

docker 安装mysql数据库

docker安装 如果不知道docker怎么安装的&#xff0c;请看docker安装教程 docker 安装mysql 拉取镜像 docker pull mysql:5.7在本地创建目录&#xff08;存放数据库文件&#xff09; 容器中的文件&#xff0c;映射到宿主机。 mkdir -p ./mysql/data ./mysql/logs ./mysql/…

FineRrport填报重复数据校验

参考&#xff1a; 校验填报页面的数据是否重复- FineReport帮助文档 - 全面的报表使用教程和学习资料 联立多字段校验是否与数据库中数据重复- FineReport帮助文档 - 全面的报表使用教程和学习资料 1、校验填报页面数据是否重复&#xff08;多列&#xff09; 1&#xff09…

Unity Recorder的使用讲解

Unity Recorder的使用讲解使用目的插件下载插件位置窗口基本介绍基本设置选项录制列表Animation Clip参数讲解Movie 电影模式参数介绍SourceGameViewTargeted Camera360ViewRender Texture AssetOutPut ReslutionInclude AudioFlip VerticalTexture SamplingFormatMedia File F…