八股

MQ怎么保证消费者顺序的?

Redis为什么这么快

  • 内存数据库
  • c语言实现
  • 优化过的数据结构
  • 单线程,避免多线切换的开销
  • I/O多路复用 一个线程处理多个I/O

Redis大key问题

大key是value过大

造成的问题:会造成堵塞

解决方案:拆分大key,删除大key(不能用del,在redis6.0之后可以用unlock)

Redis基本数据结构

string

list

hash

set

zset

Bitmaps

HyperLogLog

Geospatial

跳表

删除、插入、查找都是logN

相比平衡树、红黑树效率差不多,但是红黑树实现更复杂。跳表不稳定。

项目中Redis如何更新的?怎么保证缓存一致性

雪崩、击穿、穿透

给缓存业务添加降级限流策略。

缓存雪崩意思是设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB 瞬时压力过重雪崩。与缓存击穿的区别:雪崩是很多 key ,击穿是某一个 key 缓存。

解决方案主要是可以将缓存失效时间分散开,比如可以在原有的失效时间基础上增加一个随机值,比如 1-5 分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

雪崩:大量的key同时过期或者redis宕机。

穿透无中生有 key ,布隆过滤 null 隔离

缓存击穿过期 key ,锁与非期解难题。

雪崩大量过期 key ,过期时间要随机。

面试必考三兄弟,可用限流来保底。

Mysql

索引失效场景

使用like 左模糊匹配 左右模糊匹配

条件查询中,对索引列进行表达式计算

条件查询中,对索引列使用函数 length(name)

对索引列进行字符串=数字比较

联合索引,遵循最左原则

where子句中,or前是索引列,or后不是索引列

储存引擎

InnoDB,会默认为主键建立索引,称为聚簇索引,其他的索引叫做二级索引。

都是B+树。

聚簇索引:叶子节点 实际数字

二级索引:叶子节点 主键

MyISAM:不支持事务,也不支持行级锁和外键约束。

Memery:就是将数据放在内存中,数据处理速度很快,但是安全性不高。

日志文件:

binlog:

redolog:

undolog

relaylog

事务隔离级别

脏读

不可重复度

幻读

隔离级别:

读未提交:指一个事务还没提交时,它做的变更就能被其他事务看到

读提交:指一个事务提交之后,它做的变更才能被其他事务看到

可重复读:指一个事务执行级别过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,Mysql InnoDB引擎的默认隔离级别

串行化:会对记录加上读写锁,在多个事务对这条记录进行读写操作时,如果发生了读写冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。

JAVA

HashMap的结构

HashMap数据结构是数组和链表,HashMap通过哈希算法将元素的键(key)映射到数组中的槽位(Bucket)。如果多个键映射到同一个槽位,他们会以链表的形式存储在同一个槽位上。

当一个链表长度超过8的时候,就转成红黑树。因为链表查询是O(n)。

ArrayList LinkeList:

ArrayList 适用于频繁访问集合元素的场景,基于数组实现。

LinkedList适用于频繁插入删除和删除的场景,大小经常改变。

ArrayList扩容 1.5倍

计算新的容量、创建新的数组、复制、更新引用、完成扩容。

Linux 常用命令

  • 文件和目录操作

    • ls

      :列出目录内容。

      • ls -l:以长格式显示文件详细信息,包括文件权限、所有者、大小、修改时间等。例如ls -l /home/user/Documents会详细列出/home/user/Documents目录下的文件信息。
      • ls -a:显示所有文件,包括隐藏文件(以 “.” 开头的文件)。
    • cd:切换目录。例如cd /home/user/Downloads会将当前工作目录切换到/home/user/Downloads

    • pwd:显示当前工作目录的绝对路径。

    • mkdir:创建目录。如mkdir new_folder会在当前目录下创建一个名为new_folder的新目录。

    • rmdir:删除空目录。若目录非空,需要先删除目录中的文件。

    • rm:删除文件或目录。rm -r用于递归删除目录及其内容。例如rm -r old_folder会删除old_folder目录及其内部的所有文件和子目录。

  • 文件查看和编辑

    • cat:查看文件内容。如cat file.txt会将file.txt的内容输出到终端。
    • less:分页查看文件内容,按空格键翻页,按 “q” 键退出。适合查看大型文件。例如less big_file.log
    • vimnano:文本编辑器。在vim中,按 “i” 键进入插入模式进行编辑,按 “Esc” 键退出插入模式,然后输入 “:wq” 保存并退出,“:q!” 强制退出不保存。nano相对更简单,编辑后按 “Ctrl + O” 保存,按 “Ctrl + X” 退出。
  • 系统信息查看

    • uname:显示系统信息。uname -a会输出内核名称、主机名、内核版本等详细信息。
    • top:实时查看系统资源使用情况,包括 CPU、内存、进程等的使用信息。按 “q” 键退出。
    • df:查看磁盘空间使用情况。df -h以人类可读的方式(如 KB、MB、GB)显示磁盘使用量。
  • 进程管理

    • ps:查看进程状态。ps -ef显示所有进程的详细信息,包括 UID、PID、PPID 等。
    • kill:终止进程。例如kill PID(将 “PID” 替换为要终止的进程 ID)可以终止指定的进程,kill -9 PID是强制终止进程。
  • 文件权限管理

    • chmod:改变文件或目录的权限模式。例如chmod 755 file.txt会将file.txt的权限设置为所有者有读、写、执行权限,所属组和其他用户有读、执行权限。
    • chown:改变文件或目录的所有者。如chown user:group file.txtfile.txt的所有者设置为 “user”,所属组设置为 “group”。

Git 常用命令

  • 仓库初始化和克隆
    • git init:在当前目录初始化一个新的 Git 仓库。例如在一个新的项目文件夹中执行git init,就可以开始使用 Git 管理该项目的版本。
    • git clone [repository URL]:克隆远程仓库到本地。比如git clone https://github.com/user/repository.git会将远程仓库https://github.com/user/repository.git克隆到本地。
  • 文件操作
    • git add [file or directory]:将文件或目录添加到暂存区。例如git add file.txtfile.txt添加到暂存区,准备提交;git add.会将当前目录下的所有文件(除了被忽略的文件)添加到暂存区。
    • git commit -m “[commit message]”:提交暂存区的文件到本地仓库,并附上提交信息。如git commit -m "Initial commit"是进行初次提交并附上提交说明 “Initial commit”。
  • 分支操作
    • git branch:查看本地分支。带参数git branch [branch - name]可以创建新分支。例如git branch new - branch创建一个名为new - branch的新分支。
    • git checkout [branch - name]:切换分支。比如git checkout master会切换到master分支。
    • git merge [branch - name]:合并分支。假设在feature - branch上完成了功能开发,在master分支执行git merge feature - branch可以将feature - branch的内容合并到master分支。
  • 远程仓库操作
    • git remote add [remote - name] [remote - repository - URL]:添加远程仓库。例如git remote add origin https://github.com/user/repository.git添加一个名为origin的远程仓库。
    • git push [remote - name] [branch - name]:将本地分支推送到远程仓库。如git push origin master将本地master分支推送到名为origin的远程仓库。
    • git pull [remote - name] [branch - name]:从远程仓库拉取更新并合并到本地分支。例如git pull origin masterorigin远程仓库的master分支拉取更新。

Docker 常用命令

  • 镜像操作
    • docker pull [image - name]:从镜像仓库拉取镜像。例如docker pull ubuntu:latest会拉取最新版本的 Ubuntu 镜像。
    • docker images:列出本地所有的 Docker 镜像,显示镜像的仓库名、标签、镜像 ID、创建时间和大小等信息。
    • docker rmi [image - ID or image - name]:删除本地镜像。例如docker rmi ubuntu:latest删除本地的ubuntu:latest镜像;也可以通过镜像 ID 来删除。
  • 容器操作
    • docker run -it [image - name] [command]:创建并运行一个容器。-i表示保持标准输入打开,-t分配一个伪终端。例如docker run -it ubuntu:latest /bin/bash会创建一个基于ubuntu:latest镜像的容器,并在容器中运行/bin/bash命令,让用户可以在容器内进行交互操作。
    • docker ps:查看正在运行的容器,docker ps -a查看所有容器(包括已停止的)。显示容器的 ID、名称、创建时间、状态等信息。
    • docker stop [container - ID or container - name]:停止运行中的容器。例如docker stop my_container停止名为my_container的容器。
    • docker start [container - ID or container - name]:启动已停止的容器。
    • docker exec -it [container - ID or container - name] [command]:在运行的容器中执行命令。如docker exec -it my_container /bin/bash可以进入名为my_container的容器并打开一个新的bash终端。
    • docker rm [container - ID or container - name]:删除容器。注意,只能删除已停止的容器,除非使用docker rm -f强制删除正在运行的容器。

Tmux 常用命令

  • 会话管理

    • tmux:启动Tmux并创建一个新的会话。
    • tmux new-session - s [session - name]:创建一个名为[session - name]的新会话。例如tmux new - session - s my_session
    • tmux ls:列出所有的Tmux会话。
    • tmux attach-session - t [session - name]:连接到指定名称的会话。如tmux attach - session - t my_session连接到my_session会话。
    • tmux kill - session - t [session - name]:杀死指定名称的会话。例如tmux kill - session - t unused_session删除unused_session会话。
  • 窗口和窗格操作

    • Ctrl + b c:在当前会话中创建一个新窗口。
    • Ctrl + b n:切换到下一个窗口。
    • Ctrl + b p:切换到上一个窗口。
    • Ctrl + b &:关闭当前窗口。
    • Ctrl + b “:垂直分割窗格。
    • Ctrl + b %:水平分割窗格。
    • Ctrl + b o:在窗格之间切换。
    • Ctrl + b x:关闭当前窗格。

    设置鼠标上下滚动:

tmux set -g mouse on
  • 粘贴:

左键选中,然后ctrl+shift+c

HashMap的数据结构,线程安全么,有没有什么并发安全的HashMap。

volatitle关键字原理。

volatitle 是 Java 提供的一种轻量级的同步机制。 Java 语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量,相比于 synchronized (synchronized*称为重量级锁), volatile 更轻量级,因为它不会引起线程上下文的切换和调度。但是 volatile 变量的同步性较差(有时它更简单并且开销更低),而且其使用也更容易出错。

并发安全

创建线程的方式

继承Thread类

实现runnable接口

实现callable接口

线程池创建线程

Runable和Callable有什么区别

image-20241205020203296

Runnable接口的run方法无返回值且不能抛出受检异常

Callable接口的call方法有返回值且能抛出异常

使用Runable实现Callable功能

使用 FutureTask 包装 Runnable
  • 原理FutureTask类实现了RunnableFuture接口,而RunnableFuture接口继承了RunnableFuture接口。通过将Runnable任务包装在FutureTask中,可以获得一个具有返回值的Future对象,从而模拟Callable的功能
自定义实现类
  • 原理:创建一个自定义类实现Runnable接口,并在类中定义一个成员变量来存储任务的结果,通过在run方法中执行任务逻辑并将结果存储到成员变量中,然后提供一个方法来获取该结果,以此实现类似Callable的功能。

常见的阻塞队列

ArrayBlockingQueue:基于数组的有界阻塞队列。

LinkedBlockingQueue:基于链表的可选有界阻塞队列。

PriorityBlockingQueue:支持优先级排序的无界阻塞队列。

DelayQueue:一个使用优先级队列实现的无界阻塞队列

SynchronousQueue:一个不存储元素的阻塞队列

image-20241205020707270

image-20241205020714918

保证线程原子性:

使用 synchronized 关键字

保证可见性的方法

使用 volatile 关键字

Synchronize和Volatile关键字原理

image-20241205021141105

image-20241205022724854image-20241205022900603

image-20241205023115444

线程池

image-20241205023630853

核心线程数

image-20241205023811682线程池种类

image-20241205023844726

ThreadLocal

image-20241205025333416

单例模式

package com.wyj.singleton;
class SingleObject {
    //创建一个SingleObject对象
    // 用static 关键字修饰 表示该变量为静态变量  该类所有对象所共享的一个变量
    //下方static方法中 不能调用非Static属性
    private static SingleObject getInstance = new SingleObject();
    private String name;
    //让其构造函数为private,那么他不会被实例化
    private SingleObject (){
    }
    //获取唯一可用的对象
    // 这里用static关键字修饰的话, 当该静态方法被调用时该类就会被类加载
    public static SingleObject getSingleObject() {
        return getInstance;
    }
    void say() {
        System.out.println("hello");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
public class singleDemo {
    public static void main(String[] args) {
        // 我们并没有去new一个实例,而是调用了该实例的 自己建造实例的方法
        SingleObject object = SingleObject.getSingleObject();
        SingleObject object2 = SingleObject.getSingleObject();
        object.setName("wyj");
        object2.setName("www");
        System.out.println(object.getName());

    }
}

八股
http://example.com/post/1bb262db.html
作者
Asdaso
发布于
2024年12月17日
许可协议