1.线程池的核心参数
核心线程数、最大线程数、阻塞队列、拒绝策略、超时时间、超时时间单位。
2.什么业务场景用到线程池
使用线程池可以避免为每个web请求都创建一个新线程。
在消息队列中,消费者需要监听队列并处理接收到的消息。使用线程池可以并行处理多个消息,提高消息的消费速度。
定时任务。
3.反射主要用来干什么?
反射是一种技术,可以通过反射技术获得类的实例对象、属性、方法。可被用于动态代理。
主要有四种方式,第一种实例对象.getClass();第二种class.forName(类全路径);第三种类名.class;第四种ClassLoader.getSystemClassLoader().loadclass().
4.Synchronized锁和Reentrantlock锁的区别
1.Synchronized锁是关键字,Reentrantlock锁是类,实现了lock接口。
2.Synchronized锁无需手动加锁解锁、Reentrantlock锁需要手动lock加锁、unlock解锁。
3.Synchronized锁只有非公平,Reentrantlock锁可以公平、可以不公平。
4.Synchronized锁底层基于Monitor实现,Reentrantlock锁基于AQS队列。
5.介绍AQS
AQS是java的一个同步抽象类,本质是一个FIFO的双端队列,有头结点、尾节点。队列中的每个节点的构成有waitstatus状态位、线程对象、前后指针。最重要的是维护了一个volatile变量state。通过当前的state变量来判断是否加锁、解锁、重入。AQS有两种资源共享方式:Exclusive
(独占,只有一个线程能执行,如ReentrantLock
)和Share
(共享,多个线程可同时执行,如Semaphore
/CountDownLatch
)。
AQS 是CLH锁队列的一种变体。核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制。
6.MYSQL索引失效的原因?
1.没有遵循最左前缀法则。
2.使用了like%。
3.范围过大,mysql自动使用了全表查询。
4.or前后的字段没有同时有索引。
5.查询条件上使用了函数。
7.redis常用数据类型
String、Hash、List、set、Zset、bitmap、hypherlog。
8.为什么需要分库分表
因为数据量很大,分担某张表或者某个库的压力,提高查询效率、缓解查询热点数据造成的锁竞争问题。
9.三个线程交替打印1~100
public class DAYIN {
volatile int a = 0;
volatile int count = 0;
public void dayin1_100(){
ReentrantLock lock = new ReentrantLock();
new Thread(() -> {
while (a <= 100) {
lock.lock();
if (count % 3 == 0) {
a++;
dayin(a);
count++;
}
lock.unlock();
}
}).start();
new Thread(() -> {
while (a <= 100) {
lock.lock();
if (count % 3 == 1) {
a++;
dayin(a);
count++;
}
lock.unlock();
}
}).start();
new Thread(() -> {
while (a <= 100) {
lock.lock();
if (count % 3 == 2) {
a++;
dayin(a);
count++;
}
lock.unlock();
}
}).start();
}
public static void main(String[] args) {
DAYIN dayin = new DAYIN();
dayin.dayin1_100();
}
public static void dayin(int a) {
if (a <= 100)
System.out.println(Thread.currentThread().getId() + ":" + a);
}
}
10.redis如何实现排序?介绍zset的原生语法
zset底层如果元素多且大使用的是HT+skiplist。hashtable保存key-value,skiplist按照score进行顺序保存。否则使用ziplist。
zset key value score
11.redis的集群模式和持久化方式?
redis是主从复制、哨兵模式、cluster。
持久化方式是RDB和AOF。
RDB指的是快照方式,可用修改config文件,例如save 500 20代表500s内修改了20次,就RDB一次。默认是bgsave,bgsave指的是fork子线程去异步RDB。RDB特点是恢复快,因为磁盘I/O少,但是RDB的中途会占用大量CPU和内存资源,而且如果突然宕机会导致没有执行最后一次RDB。
AOF指的是将每条命令记录到日志当中。过程主要分为:写入AOF缓冲区、持久化到本地、命令重写。特点是恢复很慢因为需要大量磁盘I/O,好处保存数据几乎很完整。
12.HashMap底层实现?
hashmap是线程不安全的。
计算key的hash值过程:(key==null)?0:h=(key.hashcode())^h>>>16
计算数组下标:hash&(length-1)
get流程:
判断hashmap是否为空且key对应首节点是否为空,有一个为空则返回null;
否则如果首节点是key,返回对应value;
首节点不是对应key,进行链表或红黑树查找,找到返回value,否则返回null。
扩容流程:
put流程:
先判断hashmap是否为空,为空就扩容。
找到对应下标处首节点为null,直接插入。
如果不为null且key相等,覆盖。
否则如果是红黑树,插入键值对,如果是链表尾插,且如果链表长度>=8,转换为红黑树。
插入完成后如果键值对数量大于阈值,扩容。