1.threadlocal是存储在堆还是在栈中
threadLocal存储的数据是在堆中,当通过threadLocal设置一个局部变量时,实际上是将该变量存储在与当前
线程关联的threadLocalMap中,而threadLocalMap是存储在堆中。
每个线程都有自己的threadLocalMap,用于存储与该线程关联的threadLocal变量。
threadLocal的数据在栈上仅仅是一个引用,它引用了堆中的实际数据
2.死锁的原因以及如何解决
1.互斥条件:共享资源同时只能被一个线程占用
2.请求和保持资源:线程在请求其他资源时不释放已经占有的资源
3.不可剥夺条件:某个线程已经占有的资源,除非他自己释放,否则不能被抢占
4.循环等待条件:一组线程互相等待对方持有的资源,形成一个循环等待的关系
解决:
1.预防死锁:可以通过要求线程在获得所有需要的资源之前释放已经占用的资源
2.预测和恢复:一旦检测到死锁,可以采取终止一些线程来释放资源,但是代价较高
3.避免死锁:使用银行家算法,动态地分配资源来避免死锁
3.多线程的集合有哪些
1.ConcurrentHashMap:支持并发读和写操作,JDK1.7之前采用的分段锁,JDK1.8之后就使用的CAS
2.CopyOnWriteArrayList:适用于读多写少的场景。在写的时候会复制一个新的数组,写操作在新数组上进行,
读操作在旧数组上进行,当操作结束后,将索引指向新数组
3.CopyOnWriteArraySet:类似于CopyOnWriteArrayList,是一个线程安全的set实现,内部使用
CopyOnWriteArrayList来存储元素
4.ConcurrentLinkedQueue:基于链表的线程安全的队列,适用于高并发生产者-消费者模式
5.ConcurrentLinkedDeque:基于双端队列实现的线程安全的队列,适用于高并发生产者-消费者
6. BlockingQueue:是一个接口,定义了一系列阻塞操作,用于实现生产者-消费者模式。java提供了多个
BlockingQueue的实现,如LinkedBlockingQueue ArrayBlockingQueue
PriorityBlockingQueue等
7.ConcurrentSkipListMap和ConcurrentSkipListSet:基于跳表实现的线程安全的map和set实现,
支持高并发的读写操作,元素有序排列
8.Vector:线程安全的集合类,性能相对较差,使用了全局锁来保护所有操作
9.hashtable:线程安全的哈希表
4.如果一个线程在运行,我如何通知他让他停止
·1.使用标志位:在线程的执行逻辑中,定期检查一个标志位,如果标志位被设置为停止的状态,
线程就可以自行安全的停止执行。通常适用于定期轮询的情况
2.使用Thread.interrupt():如果线程正在阻塞操作(如等待IO、睡眠等),可以调用线程的interrupt()方法
来中断线程。线程需要检查isInterrupted()方法来响应中断请求并安全的停止执行
3.使用Thread.stop():会强制终止线程,可能导致线程在不安全的状态下停止。不推荐使用
4.使用ExecutorService.shutdown():如果线程是通过ExecutorService执行的,可以调用shutdown()或
shutdownNow()方法来停止线程池中所有线程
5.进程调度算法
1.先来先服务:按照进程的到达顺序依次执行
2.短作业优先:选择下一个执行的进程是最短执行时间的进程
3.剩余时间最短优先:是短作业优先的一种抢占式,它允许在当前执行进程被抢占时选择一个更短剩余执行时间
的进程来执行
4.优先级调度:每个进程都分配一个优先级,调度器选择具有最高优先级的进程来执行。优先级可以是静态的
也可以是动态的
5.时间片轮转调度:RR算法为每个进程都分配一个时间片,按照时间片的顺序轮流执行进程。如果一个进程在时间
片结束前没有执行完,它将被暂停并重新放入队列末尾。提供了公平性,但可能导致上下文切换开销较大
6.多级反馈队列调度:进程根据器行为和优先级分配到不同的队列中,每个队列可能使用不同的调度算法。
进程在队列之间移动,以适应其行为
7.实时调度算法:实时系统通常要求在严格的时间限制内完成任务
6.目前主流操作系统的进程调度算法
1.完全公平调度:CFS是linux内核中使用的默认进程调度算法。它旨在提供公平的CPU时间分配,
使用红黑树数据结构来跟踪进程的虚拟运行时间
2.实时调度:linux支持多种实时调度算法,如先来先服务等
3.多级反馈队列调度:windows使用多级反馈队列调度算法,将进程分为多个队列,每个队列具有不同
的优先级。进程可以在不同队列之间移动
9.https过程
客户端发起连接:客户端通过URL或者其他方式向服务端发起HTTPS连接请求。HTTPS使用的默认端口号是443
(1)服务端配置:服务端需要配置支持HTTPS的服务器,并在它上边安装一个数字证书。证书用于证明服务端的
身份,证书包含服务端的公钥以及其他信息,并通过CA的数字签名来验证
(2)握手过程:
客户端:客户端向服务端发送一个连接请求,其中包括支持的加密算法、随机数和其他信息
服务端:服务端从支持的加密算法中选择一个,然后向客户端发送连接请求,包括服务端的数字证书
和另一个随机数
数字证书验证:客户端使用自己存储的根证书或操作系统/浏览器内置的根证书列表来验证服务端的数字
证书的有效性和真实性。如果验证失败,连接终止
共享密钥协商:客户端生成一个临时的对称密钥,然后使用服务端的公钥加密这个密钥,并发送给服务
端。服务端使用自己的私钥解密,得到会话密钥
数据加密:一旦会话密钥被双方确认,它将用于加密和解密传输的数据。
安全通信:客户端和服务端之间建立了安全通信渠道后,可以开始进行安全的HTTP通信
10.TCP是如何保证可靠传输的
1.流量控制:用于确保发送方不会以过快的速度向接收方发送数据,以防止接收方的缓冲区溢出。
TCP的流量控制通过滑动窗口来实现
(1)发送窗口:发送方维护一个发送窗口的大小,表示可以发送的数据量。接收方在确认收到数据后通知发送
方,发送窗口的大小可以动态调整
(2)接收窗口:接收方维护一个接收窗口的大小,表示可以接收的数据量。接收方通过TCP头中的确认号和窗口
字段来通知发送方,告诉它可以发送多少数据
(3)流量控制机制使得发送方可以根据接收方的处理能力来动态调整发送速率,以避免数据丢失或溢出
2.拥塞控制:拥塞控制用于避免网络中的拥塞情况,以确保网络资源被有效地利用。拥塞控制是基于网络的状态
和性能动态调整发送速率的机制
(1)拥塞窗口:发送方维护一个拥塞窗口的大小,表示可以发送的数据量。拥塞窗口的大小根据网络的拥塞程度
动态调整
(2)拥塞控制使用算法如拥塞避免和拥塞恢复等,以避免过快的向网络发送数据,并在检测到拥塞时减小发送速率
3.超时重传:超时重传用于处理丢失的数据包或失序的数据包。当发送方发送数据并等待一段时间没有收到确认
时,它会建设数据包以丢失,并将数据包重新发送
11.MVCC是什么
是数据库用于处理并发访问的一种机制。它允许多个事务同时读取和修改数据库,而不会导致数据的不一致性或冲突。
MVCC的核心思想是在数据库中维护多个版本的数据,并根据事务的隔离级别来决定事务能够看到哪个版本的数据。
1.版本号:在MVCC中,每一行数据都有一个版本号。当一个事务对数据进行修改时,它会为该行数据创建一个新的
版本,并将新版本的版本号更新。这样,每个数据行都可以有多个不同的版本,每个版本都有自己的时间戳
2.事务可见性:MVCC根据事务的时间戳来决定哪个版本的数据对事务是可见的。在读已提交隔离级别下,事务只能
看到已提交的版本数据。在可重复读的隔离级别下,事务在整个事务期间看到的数据版本都是一致的,
不受其他事务的影响
3.事务冲突:如果两个事务同时尝试修改同一行数据,MVCC会检测到冲突,其中一个事务将被阻塞,
直到另一个事务完成。确保了数据的一致性
4.回滚段:MVCC通过回滚段来存储旧版本的数据。回滚段是一个特殊的存储区域,用于存储已被修改的数据的
旧版本。这允许事务在需要回滚时恢复到先前的数据状态
5.垃圾回收:为了避免无限增长的数据版本,MVCC会定期进行垃圾回收,删除不再需要的旧版本数据
12.隔离级别
1.读未提交:一个事务可以读取另一个事务未提交的数据。可以发生脏读、不可重复读和幻影读等问题。虽然
提供了最高的并发性,但牺牲了数据的一致性和完整性
2.读已提交:这是mysql默认的隔离级别,一个事务只能读取到已经提交的数据,避免了脏读问题
3.可重复读:一个事务在整个事务期间看到的数据是一致的,不会发生不可重复读问题。但是可能因为其它事务
插入新数据行而产生幻读
4.串行化:事务之间是串行执行的,不会发生任何并发问题
设置隔离级别:
set transaction isolation level 隔离级别(READ UNCOMMITTED | READ COMMITTED |
REPEATABLE READ | SERIALIZABLE)
13.spring如何解决循环依赖
通过三级缓存解决循环依赖
1.singletonObjects:这个缓存存储了已经完全初始化的单例bean对象。当一个bean完全初始化后,
它将会被放入这个缓存中。这个缓存通常用于正常的单例bean,而不涉及循环依赖
2.eralySingletonObjects:这个缓存存储了正在创建过程中的单例bean对象。当一个bean正在创建但还没有
完全初始化时,它会被放入这个缓存中。这个缓存用于解决循环依赖问题。
3.singletonFactories:这个缓存存储了bean的工厂对象,而不是bean本身。这些工厂对象用于创建bean实
例。用于解决循环依赖问题
循环依赖产生的情况:通常发生在两个或多个bean互相依赖的情况下。例如,bean A 依赖 bean B,
而bean B 也依赖 bean A。当spring容器尝试实例化这些bean时,它会陷入循环依赖的情况。
解决循环依赖步骤:
(1)当容器启动时,它会创建一个空的早期单例bean缓存(earlySingletonObjects)和一个工厂缓存
(singletonFactories)
(2)当容器实例化一个bean时,它会首先检查earlySingletonObjects缓存中是否存在该bean的早期实例。
如果存在,它会返回该实例,而不会再次创建
(3)如果earlySingletonObjects缓存中不存在该bean的早期实例,容器将尝试创建bean的实例,并将其存储在
earlySingletonObjects缓存中,但此时bean可能还没有完全初始化
(4)当bean的创建过程需要依赖于其它bean时,容器会继续创建这些依赖bean。如果依赖的bean也存在循环依赖
,容器将从singletonFactories缓存中获取相应的bean工厂
(5)当bean的创建过程完成后,容器将bean实例存储在singletonObjects缓存中,表示该bean已经完全初始化
14.如何处理敏感字
1.敏感字过滤:使用敏感字过滤器,用于检测和替换文本中的敏感字或违规内容。通常,敏感字列表会存储在一个
数据库或配置文件中,应用程序会定期检查文本内容并进行过滤。过滤可以替换敏感字为 * 或者
其它字符,或者直接删除掉敏感字
2.白名单和黑名单:白名单包括允许的单词或表情字符,而黑名单包括禁止的单词或表情字符。用户提交的内容
可以与白名单和黑名单进行比对,从而进行过滤或拒绝
3.自定义规则:特定的敏感内容需要自定义规则,来识别和处理不同类型的敏感内容,如手机号码、
电子邮件地址、银行卡号等
4.机器学习和NLP:使用机器学习和NLP技术来检测和处理敏感内容。这些方法可以学习用户生成内容的模式,
并自动识别和处理敏感内容