JAVA面经整理(2024.6)(一)

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,转换为红黑树。

插入完成后如果键值对数量大于阈值,扩容。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值