Java 中能创建 volatile 数组吗?
能,Java 中可以创建 volatile 类型数组,不过只是一个指向数组的引用,而不是整个数组。我的意思是,如果改变引用指向的数组,将会受到 volatile 的保护,但是如果多个线程同时改变数组的元素,volatile 标示符就不能起到之前的保护作用了。
你是如何调用 wait()方法的?使用 if 块还是循环?为什么?
wait() 方法应该在循环调用,因为当线程获取到 CPU 开始执行的时候,其他条件可能还没有满足,所以在处理前,循环检测条件是否满足会更好。下面是一段标准的使用 wait 和 notify 方法的代码:
// The standard idiom for using the wait method synchronized(obj) { while(condition does not hold) obj.wait(); // (Releases lock, and reacquires on wakeup) ... // Perform action appropriate to condition
Java 中怎么获取一份线程 dump 文件?
在 Linux 下,你可以通过命令 kill -3 PID (Java 进程的进程 ID)来获取 Java 应用的 dump 文件。在 Windows 下,你可以按下 Ctrl + Break 来获取。这样 JVM 就会将线程的 dump 文件打印到标准输出或错误文件中,它可能打印在控制台或者日志文件中,具体位置依赖应用的配置 也可以使用jstack 工具dump
为什么 Java 中的 String 是不可变的(Immutable)?
Java 中的 String 不可变是因为 Java 的设计者认为字符串使用非常频繁,将字符串设置为不可变可以允许多个客户端之间共享相同的字符串。
阻塞io、nio、aio、信号驱动io、异步io
cloud.tencent.com/developer/a…
epoll相对select
- epoll 可以支持到数万的文件描述符,而select默认只支持1024
- select 每次都需要把所有的描述符全部发送到内核态做全部扫描判断是否有io请求,epoll 则是内核空间与用户空间共享一块内存,只需要在内核空间注册一个事件表,然后等待事件的通知即可,不需要对已注册的文件描述符进行遍历。
- epoll 维护了一个就绪队列,能很快的知道是否存在io
Netty的零拷贝(Zero-Copy)主要体现在五个方面
Netty接收和发送ByteBuffer采用DirectBuffer,使用堆外直接内存进行Socket读写,不需要进行字节缓冲区的二次拷贝。如果使用传统的JVM的堆内存(Heap Buffer)进行socker读写,那么JVM将会将堆内存拷贝一份到直接内存中,然后在写入socket中。相比堆外直接内存,消息在发送过程中多了一次缓存区的拷贝
Netty提供CompositeByteBuf组合缓冲区类,可以将多个 ByteBuf合并为一个逻辑上的ByteBufer,避免了各个ByteBufer之间的拷贝,将几个小buffer合并成一个大buffer的繁琐操作。
CompositeByteBuf可以把需要合并的多个ByteBuf组合起来,对外 提供统一的readIndex和writerIndex。CompositeByteBuf只是在逻辑 上是一个整体,在CompositeByteBuf内部,合并的多个ByteBuf都是单 独存在的。CompositeByteBuf里面有一个Component数组,聚合的 ByteBuf都放在Component数组里面,最小容量为16。 Netty提供了ByteBuf的浅层复制操作(slice、 duplicate),可以将ByteBuf分解为多个共享同一个存储区域的 ByteBuf,避免内存的拷贝
Netty进行文件传输时,可以调用FileRegion包装的 transferTo()方法直接将文件缓冲区的数据发送到目标通道,避免普通的循环读取文件数据和写入通道所导致的内存拷贝问题。
在将一个byte数组转换为一个ByteBuf对象的场景下,Netty 提供了一系列的包装类,避免了转换过程中的内存拷贝。
为什么tcp 挥手需要4次
因为被动断开放收到断开请求后不能里面关闭连接,可能还有未处理玩的数据,只能先返回一个收到关闭的确认,等处理完后发送fin确认可以关闭,随后主动close放等待time-wait时间过后关闭
cms和g1
cms 标记清除算法,容易产生内存碎片,多线程清理延迟较低 g1 标记复制(压缩) 不会产生太多内存碎片,按照区域回收,在内存较大的应用中有明显的优势
对象分配内存方式
- 指针碰撞,适合垃圾回收算法带内存整理的例如,Parallel
- 内存使用情况表(空闲列表),适合不带内存整理的,例如cms
多线程为什么不安全?
究其根本,是因为线程之间无法准确的知道互相之间的状态。那么如何使得多线程安全呢,从内存角度来讲,保证线程的工作内存之间的可见性和有序性,是多线程并发安全的基础。例如volatile关键字和synchronized关键字,我们除了从作用上了解他们,还可以从更深层的内存语义上理解,他们之所以能够一定程度的解决线程安全问题,是因为他们约束了一定的内存处理方式!
对象的访问定位
直接指针和句柄
mysql binlog 有几种格式
- Statement格式是最早出现的binlog格式,它记录了每个执行的SQL语句。当数据库执行一个语句时,该语句将会被完整地写入到binlog中。这意味着binlog中会记录所有的SQL语句,包括对表的修改操作和查询操作。Statement格式的优点是记录量相对较小,因为它只需要记录SQL语句本身而不需要记录具体的行数据。另外,由于只记录SQL语句,所以binlog文件可以被直接读取和解析,方便进行数据分析和处理。 然而,Statement格式也有一些缺点。首先,当某些SQL语句引用了非确定性函数(如NOW())或者使用了触发器等特性时,binlog的回放可能会产生不一致的结果。其次,由于binlog只记录了SQL语句,因此在进行数据恢复时,可能需要重新执行大量的SQL语句,导致恢复效率较低
- Row格式是MySQL binlog中的第二种日志录入格式,它记录了每一行数据的变化。当数据库执行一个修改表数据的SQL语句时,Row格式会将修改前后的行数据都记录到binlog中。 Row格式的优点是可以确保数据的一致性,因为它记录了具体的行数据。这样,当进行数据恢复时,可以直接使用binlog中的行数据来还原数据库的状态,而不需要重新执行SQL语句。另外,Row格式也避免了Statement格式可能存在的不确定性问题。 然而,Row格式的缺点是记录量相对较大,因为它需要记录每一行数据的变化。当数据量比较大时,binlog文件可能会变得非常庞大,占用大量的存储空间。
- Mixed格式是MySQL binlog的第三种日志录入格式,它是Statement格式和Row格式的混合形式。Mixed格式会根据具体的SQL语句类型来选择使用哪种格式进行记录。 Mixed格式的优点是可以兼顾Statement格式和Row格式的优点。对于简单的SQL语句,可以使用Statement格式进行记录,减少binlog文件的大小;对于复杂的SQL语句,可以使用Row格式来确保数据的一致性。这样既可以减少存储空间的占用,又可以保证数据的完整性。 然而,Mixed格式也有一些缺点。首先,由于需要根据具体的SQL语句类型进行判断,因此在进行binlog解析时可能会比较复杂。其次,由于需要同时记录Statement格式和Row格式的日志,可能会增加binlog文件的大小。
innodb 4大特性
- 原子性(Atomicity):事务中的操作要么全部成功,要么全部失败。原子性通过[undo log]
- 一致性 : 数据库总是从一个一致性的状态转换到另外一个一致性的状态。例如,A转账给B 100块钱,即使中间SQL执行过程中系统崩溃,A也不会损失100块,因为事务没有提交,修改也就不会保存到数据库。
- 隔离性:一个事务的修改在最终提交前,对其他事务是不可见的。隔离性通过读写锁+[MVCC]实现。
- 持久性:一旦事务提交,所做的修改就会永久保存到数据库中。持久性通过redo log实现。 以上四个属性通常称为ACID特性,其中C(一致性)是目的,A(原子性)、I(隔离性)、D(持久性)是手段。
mysql,如果一个表有一列定义为TIMESTAMP,将发生什么
每当行被更改时,时间戳字段将获取当前时间戳。
BLOB 和 TEXT 有什么区别
- TEXT 用于存储非二进制字符串,它需要指定字符集,并按照该字符集进行校验和排序。TEXT 类型主要用于存储纯文本数据,在某些情况下,当变量的长度超过 VARCHAR 的限制时,可以使用 TEXT 作为扩展。1
- BLOB 用于存储二进制数据,它不需要指定字符集,因为二进制数据不依赖于字符集。BLOB 类型不仅可以存储文本信息,还可以保存图片等其他类型的数据。BLOB 可以看作是 VARBINARY 在长度不足时的扩展。
两者之间的相同点包括:
- 都不允许有默认值。
- 保存或检索数据时不会删除尾部的空格。
- 在索引blob或text上,必须执行索引前缀的长度。
可以使用多少列创建索引
16 个
如何优化distinct
- 增加索引
- 优化查询语句
- 使用子查询
- 在有索引的情况下 distinct 和group by性能差不多,无所有的情况distinct 优于group by (filesort)
mysql日期函数 now 和current_date区别
now 包含时分秒 current——date不包含
mysql索引匹配
- 最左前缀匹配原则,mysql会一直向右匹配直到遇到范围查询**(>、<、between、like)就停止匹配
mysql 数据库优化
- 优化数据库表结构的设计,为什么数据库表的设计会影响性能? 字段的数据类型:不同的数据类型的存储和检索方式不同,对应的性能也不同,所以说要合理的选用字段的数据类型。比如人的年龄用无符号的unsigned tinyint即可,没必要用integer数据类型的长度:数据库最终要写到磁盘上,所以字段的长度也会影响着磁盘的I/O操作,如果字段的长度很大,那么读取数据也需要更多的I/O, 所以合理的字段长度也能提升数据库的性能。比如用户的手机号11位长度,没必要用255个长度。表的存储引擎:常用的存储引擎有MyISAM、InnoDB、Memory,不同的存储引擎拥有不同的特性,所以要合理的利用每种存储引擎的长处和优点来提供数据的性能。MyISAM不支持事务,表级锁,但是查询速度快,InnoDB支持事务,行锁。
- SQL优化 MySQL性能优化的一个很重要的手段就是对SQL语句的优化。其中最重要的方式就是使用索引。
- 分表 当一个表的数据量很大的时候,查询就变的很慢,所以减少表里的记录的数量是优化的一种方式,这种方式就是将一张表的数据拆分成多张表,这样每张表的数量就减少了,这样查询速度就相对来说就快了一些。 大表对DDL操作有一定的影响,如创建索引,添加字段 修改表结构需要长时间锁表,会造成长时间的主从延迟,影响正常的数据操作
- 大事务 大事务:运行时间比较长,操作的数据比较多的事务 风险:锁定太多的数据,造成大量的阻塞和锁超时,回滚时所需时间比较长,执行时间长容易造成主从延迟 避免一次处理太多的数据,移除不必要在事务中的select操作
- 数据库参数配置优化(很重要) mysql是一个高度定制化的数据库系统,提供了很多配置参数(如最大连接数、数据库占用的内存等),这些参数都有默认值,一般默认值都不是最佳的配置,一般都需要根据应用程序的特性和硬件情况对mysql的配置进行调整。 例如最大连接数默认为100,即使SQL语句优化的再好,硬件设备配置再高,当请求超过100时都要再等待,这就是配置不合理导致MySQL不能发挥它的最大能力。
- 主从复制,读写分离 一台MySQL服务器同一时间点支持的并发数是有限的,当大量并发(如秒杀活动等,很多用户都同一时刻访问数据库)时,一台数据库处理不过来,所以增加MySQL服务器的数量也是一种增强数据库性能的方式。 通过使用MySQL主从复制,增删改操作走Master主服务器,查询走Slaver从服务器,这样就减少了只有一台MySQL服务器的压力。
- 增加缓存层 减少数据库连接也是一种优化手段,有些查询可以不用访问数据库,可以通过使用缓存服务器如redis、memcache、elasticsearch等增加缓存,减少数据库的连接
- 升级服务器硬件
mysql 唯一索引和主键索引哪个快
主键索引快,因为唯一索引需要先查询唯一索引树,在拿到主键id后回表查询主键树找到对应的数据
漏斗和令牌桶
漏斗 处理不了突发流量,强制限制了流量速率 令牌桶支持突发流量
Java中interrupted 和 isInterruptedd方法的区别?
interrupted() 方法是一个[静态方法]用于检查当前线程的中断状态并清除中断状态;而 isInterrupted() 方法是一个[实例方法],用于检查线程的中断状态但不会清除中断状态。
如何退出线程
- 使用退出标志
- interrupted
线程的优先级
setPriority
execute和submit 的区别
两者主要区别,其实还是在于有无返回值,实际生产中为了更好的处理异常,使用submit更多一点。
线程池有哪些状态
在Java中,线程池的状态主要包括RUNNING(运行)、SHUTDOWN(关闭)、STOP(停止)和TIDYING(整理)等。这些状态由ThreadPoolExecutor类中的ctl字段管理,ctl字段的高3位表示线程池的状态,低29位表示线程的数量。以下是线程池的几种状态:
RUNNING(运行):
表示线程池处于正常运行状态。 线程池被创建后一直处于运行状态,当调用shutdown()方法时,会切换到SHUTDOWN状态。 SHUTDOWN(关闭):
表示线程池正在关闭状态。 当调用shutdown()方法后,线程池会拒绝新任务,但会继续处理已经提交的任务。 STOP(停止):
表示线程池停止状态。 当调用shutdownNow()方法后,线程池会拒绝新任务,并尝试停止所有正在执行的任务。 TIDYING(整理):
表示线程池正在整理状态。 在所有任务都已经终止,工作线程数量为零时,线程池会切换到这个状态。 TERMINATED(终止):
表示线程池已经终止状态。 在整理完毕后,线程池会切换到这个状态。
spring mvc dispatcher工作流程
mq 常见问题
消息丢失、消息重复消费、消息保证顺序
redis 的回收使用的是什么算法
LRU 最少使用淘汰
假如 Redis 里面有 1 亿个 key,其中有 10w 个 key 是以某个固定的已知的前缀开头的,将它们全部找出来
scan 命令
redis 的 持久化选择
RDB:每隔一段时间把整体的二进制数据作为快照存下来,文件相对小,更容易丢失部分消息 AOF:记录每个命令(重写优化),文件相对较大,不易丢消息
netty 的高性能表现
(1) IO线程模型 :同步非阻塞,用最少的资源做更多的事情,即IO多路复用。 (2) 内存零拷贝 :尽量减少不必要的内存拷贝,实现了更高效率的传输。 (3) 内存池设计 :申请的内存可以重用,主要指直接内存。内部实现是用一颗二叉查找树管理内存分配情况。 (4) 串行化处理读写 :避免使用锁带来的性能开销。即消息的处理尽可能再同一个线程内完成,期间不进行线程切换,这样就避免了多线程竞争和同步锁。表面上看,串行化设计似乎CPU利用率不高,并发程度不够。但是,通过调整NIO线程池的线程参数,可以同时启动多个串行化的线程并行运行,这种局部无锁化的串行线程设计相比一个队里-多个工作线程模型性能更优。 (5) 高性能序列化协议 :支持protobuf等高性能序列化协议。