面试java复习

jvm

       jvm运行时内存区域

       对象创建过程(加载、解析、初始化)

       对象内存布局【对象头(gc分代年龄信息,hashcode,锁状态标志,类型指针),实例数据,对齐填充】

       垃圾回收器与内存分配策略

                对象是否已死(引用计数(循环引用),可达性分析)    

                对象引用(强,弱,软,虚) 

                垃圾回收算法

                        标记清除。产生内存碎片

                        复制算法。空间利用率低

                        标记整理。

                        分代回收。新生代(8-1-1),老年代,永久代     

                垃圾回收器        

                        serial。单线程收集器

                        parnew。多线程收集器

                        parallel。并行收集器

                        concurrent。并发收集器

                        parallel scavenge。并行的多线程收集器 标记整理

                        cms。最短回收停顿时间 标记清除

                        g1 面向服务端的收集器

                类加载

                        类生命周期: 加载 连接 初始化 使用 卸载

                        类加载器

                                启动类加载器

                                扩展类加载器

                                引用程序类加载器

                        双亲委派模型

                                如果一个类加载器收到一个类加载的请求,它首先不会自己加载,而是把这个请求委派给父类加载器。只有父类无法完成时子类才会尝试加载。

java基础

封装 继承 多态 反射

volatile

        保证线程可见性和有序性,不保证线程安全

transient

        只作用于变量,不会被序列化,存在于内存中

object方法

        getclass

        tostring

        equals

        hashcode

        clone

        finalize

设计模式

        单例模式

        工厂模式

        代理模式

        装饰器

        观察者

        模版方法

        策略模式

数据结构和算法 

数据结构

        数组

        链表

                链表逆序

        树

                遍历

                二叉树左右子树转化

算法

        排序算法

                选择

                冒泡        

        递归

                递归开始,递归内容,递归结束

        滑动窗口

                双指针的一种思想,两个指针指向的元素之间形成一个窗口。

        动态规划

                如果一个问题,可以把所有可能的答案穷举出来,并且穷举出来后,发现存在重叠子问题,就可以考虑使用动态规划。

                如最长递增子序列、最小编辑距离、背包问题、凑零钱问题

        深度遍历

        广度遍历

        贪心算法

                局部最优解:找零

集合


        //List
        List<String> list = new ArrayList<>();
        list.add("a");//底层是数组 扩容 新数组复制
        List<String> linkedlist = new LinkedList<>();
        linkedlist.add("e");//底层是双向列表 不扩容
        List<String> vector = new Vector<>();//底层是数组 扩容 synchronized 线程安全
        vector.add("e");
        //set
        Set<String> hashSet = new HashSet<>();
        hashSet.add("a");//底层是hashmap 扩容
        LinkedHashSet<String> linkedSet = new LinkedHashSet<>();
        linkedSet.add("b");//底层是linkedHashmap 扩容
        TreeSet<String> treeSet = new TreeSet<>();
        treeSet.add("b");//底层是treemap 红黑树 不扩容
        //map
        Map<String,String> map = new HashMap<>();
        map.put("a","b");//底层数组+链表/红黑树
        LinkedHashMap<String,String> linkedMap = new LinkedHashMap<>();
        linkedMap.put("a","b");//底层是hashmap,维护了一个双向链表,linkedhashmap.entry,继承自hashmap.node
        Map<String,String> treeMap = new TreeMap<>();
        treeMap.put("a","b");//底层是红黑树
        Hashtable<String,String> hashtable = new Hashtable<>();
        hashtable.put("a","b");//底层是数组+链表 synchronized 线程安全
        ConcurrentHashMap<String,String> cHashMap = new ConcurrentHashMap<>();
        cHashMap.put("a","b");//底层是hashmap 线程安全 1。bucket无值,compareAndSwapObject 2。bucket有值,synchronized 锁bucket桶列表

io流

 IO和NIO

        IO 面向流,阻塞io

        NIO 面向缓冲,非阻塞io,也是多路复用的基础  

        每连接每线程模型  。      消耗cpu资源

        NIO主要有三大核心部分:Channel(通道),Buffer(缓冲区), Selector。         

        NIO的主要事件有几个:读就绪、写就绪、有新连接到来。

        1.最简单的reactor模式 

注册所有感兴趣的事件处理器,单线程轮询选择就绪事件,执行事件处理器。

        

仔细分析一下我们需要的线程,其实主要包括以下几种:

  1. 事件分发器,单线程选择就绪的事件。
  2. I/O处理器,包括connect、read、write等,这种纯CPU操作,一般开启CPU核心个线程就可以。
  3. 业务线程,在处理完I/O后,业务一般还会有自己的业务逻辑,有的还会有其他的阻塞I/O,如DB操作,RPC等。只要有阻塞,就需要单独的线程。

        对于Redis来说,由于服务端是全局串行的,能够保证同一连接的所有请求与返回顺序一致。这样可以使用单线程+队列,把请求数据缓冲。然后pipeline发送,返回future,然后channel可读时,直接在队列中把future取回来,done()就可以了。

涉及到事件分发器的两种模式称为:Reactor和Proactor

标准/典型的Reactor:

  • 步骤1:等待事件到来(Reactor负责)。
  • 步骤2:将读就绪事件分发给用户定义的处理器(Reactor负责)。
  • 步骤3:读数据(用户处理器负责)。
  • 步骤4:处理数据(用户处理器负责)。

改进实现的模拟Proactor:

  • 步骤1:等待事件到来(Proactor负责)。 
  • 步骤2:得到读就绪事件,执行读数据(现在由Proactor负责)。(异步)
  • 步骤3:将读完成事件分发给用户处理器(Proactor负责)。(异步)
  • 步骤4:处理数据(用户处理器负责)(异步)

  • 在Proactor模式中,事件处理者(或者代由事件分发器发起)直接发起一个异步读写操作(相当于请求),封装了读写请求的处理逻辑,而实际的工作是由操作系统来完成的。

nio好处

  • 事件驱动模型
  • 避免多线程
  • 单线程处理多任务
  • 非阻塞I/O,I/O读写不再阻塞,而是返回0
  • 基于block的传输,通常比基于流的传输更高效
  • 更高级的IO函数,zero-copy
  • IO多路复用大大提高了Java网络应用的可伸缩性和实用性

select、poll、epoll

  • select、poll 基于轮询机制
  • epoll基于os支持的I/O通知机制。epoll支持水平触发和边沿触发两种模式。

多线程

        多线程的创建和使用

        //1.继承thread
        new Thread(){
            @Override
            public void run() {
                System.out.println("abd");
            }
        }.start();
        //2.实现runnable
        new Thread(() -> {
            System.out.println("abd");
        }).start();
        //3.实现collable接口 有返回值
        Object call = new CallableImpl().call();
        //4.线程池
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                10, //核心线程数
                10, //最大线程数
                20, //空闲线程存活时间
                TimeUnit.MINUTES, //单位
                new ArrayBlockingQueue<Runnable>(20), //阻塞对列
                Executors.defaultThreadFactory(), //线程创建工厂
                new ThreadPoolExecutor.AbortPolicy()); //拒绝策略
        //AbortPolicy:中止策略。默认的饱和策略,抛出未检查的RejectedExecutionException。
        //DiscardPolicy:抛弃策略。
        //DiscardOldestPolicy:抛弃最旧的策略
        //CallerRunsPolicy:调用者运行策略。
        //提交任务
        threadPool.submit(()->{});//可提交runnable 和 callable任务
        threadPool.execute(()->{});//可提交runnable
        //阻塞队列 lock锁
        ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(20);//列表形式的工作队列
        LinkedBlockingQueue linkedBlockingQueue = new LinkedBlockingQueue(20);//链表形式的工作队列
        SynchronousQueue synchronousQueue = new SynchronousQueue();//SynchronousQueue不是一个真正的队列,而是一种在线程之间移交的机制。
        PriorityBlockingQueue priorityBlockingQueue = new PriorityBlockingQueue(10);//优先级队
        DelayQueue delayQueue = new DelayQueue();//延迟队列
        //放
        // offer 添加元素 满返回false
        // add 添加元素 满抛异常
        // put 添加元素 阻塞
        //取
        // poll 移出并返回队列头元素 无null
        // remove 移出并返回头元素 无抛异常
        // take 移出并返回头元素 阻塞

        线程状态 

        thread方法

join 方法表示调用此方法的线程被阻塞,仅当该方法完成以后,才能继续运行

setPriority 提高线程的优先级

setdomain 守护线程,主线程结束守护线程也结束

        线程同步

//锁synchronized 与 Lock的异同?
// 同:都是用于解决线程安全问题
//异:①、Lock是显示锁,需要我们自己手动开启和关闭;synchronized是隐式锁,出了作用域就会自动释放锁。
// ②、Lock只有代码块锁,synchronized有代码块锁和方法锁。
// ③、Lock锁性能好,拓展性好。

        线程通信

//1。notify和wait
//wait():当前线程阻塞,并释放锁
//notify():当前线程唤醒被wait的其他一个线程,谁的优先级高就唤醒谁
//notifyAll():当前线程唤醒all被wait的线程

//2。lock的condition通信

//3。阻塞队列实现通信

        lock锁底层原理

public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
//tryAcquire
 final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            //volatile
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
//acquireQueued 循环获取锁
final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
//加入到阻塞队列
private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        Node pred = tail;
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node);
        return node;
    }
//Unsafe 直接操作内存
compareAndSwap

        threadlocal

线程本地变量

ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
            table = new Entry[INITIAL_CAPACITY];
            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
        }
//其实是一个entry数组

spring框架

ioc和aop

aop相关注解

@aspect,@pointcut

aop五大通知类型(前置通知,后置通知,环绕通知,最终通知,异常通知)

spring事务失效场景

1.访问修饰符必须是public

2.类未被spring管理

3.方法内部调用

4.异常回滚类型与方法抛出异常不一致

5.吞了异常

6.错误的传播特性

springboot框架

连接:http://t.csdn.cn/WLBwF

微服务springcloud

//更改负载均和策略
@Bean
  public IRule ribbonRule() {
    // 负载均衡规则,改为随机
    return new RandomRule();
  }

1.gateway

   网关路由

        loadbanlancefactory,ribbon的阻塞式拦截器

        reactiveloadbanlancefactory

   网关过滤器

        globalfilter 全局过滤器

        gatewayfilter 自定义网关路由过滤器

   全局异常拦截器

   服务返回异常拦截

   routefunction

        自定义一个api

    

@Configuration
public class RouteConfiguration {

    @Bean
    public RouterFunction routerFunction()
    {
        return RouterFunctions.route(
                RequestPredicates.GET("/code").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
                new HandlerFunction<ServerResponse>() {
                    @Override
                    public Mono<ServerResponse> handle(ServerRequest serverRequest) {
                        return ServerResponse.status(HttpStatus.OK).body(BodyInserters.fromObject("success"));
                    }
                });
    }

}

2.熔断器

(112条消息) springcloud之hystrix(熔断机制)_hystrix 异常比例_QiYang1024的博客-CSDN博客https://blog.csdn.net/QiYang1024/article/details/107773545

3.feign调用

4.注册中心

        nacos和eureka

        不同
(82条消息) 详解Nacos和Eureka的区别_梨瓜的博客-CSDN博客_nacos和eureka的区别https://blog.csdn.net/weixin_43776652/article/details/120874245

5.服务负载均衡

缓存redis

        redis数据结构

        string,hash,list,set,zset

        redis 本身有持久化,为什么还要写进 mysql 呢?

RDB :快照形式是直接把内存中的数据保存到⼀个 dump ⽂件中,定时保存,保存策略。
AOF :把所有的对 Redis 的服务器进⾏修改的命令都存到⼀个⽂件⾥,命令的集合。
RDB 会丢数据, AOP 性能不⾏
有改动先插⼊数据库,再插缓存,⽐较靠谱但性能⼀般;
有改动先插缓存,批量更新到数据库,靠谱度略差,但性能好。

        redis的数据结构和各种应⽤场景?

a. 更多的数据结构;
b. 可持久化;
c. 计数器;
d. 发布 - 订阅功能;
e. 事务功能;
f. 过期回调功能;
g. 队列功能;
h. 排序、聚合查询功能

        redis缓存问题

缓存穿透:大量请求根本不存在的key(下文详解)

缓存雪崩:redis中大量key集体过期(下文详解)

缓存击穿:redis中一个热点key过期(大量用户访问该热点key,但是热点key过期)

穿透解决方案:

        对空值进行缓存
        设置白名单
        使用布隆过滤器
        网警
雪崩解决方案

        进行预先的热门词汇的设置,进行key时长的调整
        实时调整,监控哪些数据是热门数据,实时的调整key的过期时长
        使用锁机制
击穿解决方案

        进行预先的热门词汇的设置,进行key时长的调整
        实时调整,监控哪些数据是热门数据,实时的调整key的过期时长
        使用锁机制

        setnx命令

将 key 的值设为 value,当且仅当 key 不存在。

        redis分布式锁

private void lock(int couponId,String uuid,String lockKey){

        //lua脚本(可固定写法)
        String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";

        Boolean nativeLock = redisTemplate.opsForValue().setIfAbsent(lockKey,uuid,Duration.ofSeconds(30));
        System.out.println(uuid+"加锁状态:"+nativeLock);
        if(nativeLock){
            //加锁成功

            try{
                //TODO 做相关业务逻辑(自定义)
                TimeUnit.SECONDS.sleep(10L);

            } catch (InterruptedException e) {

            } finally {
                //解锁
                Long result = redisTemplate.execute( new DefaultRedisScript<>(script,Long.class),Arrays.asList(lockKey),uuid);
                System.out.println("解锁状态:"+result);

            }

        }else {
            //自旋操作
            try {
                System.out.println("加锁失败,睡眠5秒 进行自旋");
                TimeUnit.MILLISECONDS.sleep(5000);
            } catch (InterruptedException e) { }

            //睡眠一会再尝试获取锁
            lock(couponId,uuid,lockKey);
        }
    }

        redis主从同步

Redis全量同步是通过RDB内存快照文件实现,增量同步则是将主机收到的写命令传播给从机。

         Redis哨兵(Sentinel)模式

用文字描述一下故障切换(failover)的过程。假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。这样对于客户端而言,一切都是透明的。

         redis底层通信模型

  1. Redis 服务器启动,开启主线程事件循环(Event Loop),注册 acceptTcpHandler 连接应答处理器到用户配置的监听端口对应的文件描述符,等待新连接到来;
  2. 客户端和服务端建立网络连接;
  3. acceptTcpHandler 被调用,主线程使用 AE 的 API 将 readQueryFromClient 命令读取处理器绑定到新连接对应的文件描述符上,并初始化一个 client 绑定这个客户端连接;
  4. 客户端发送请求命令,触发读就绪事件,服务端主线程不会通过 socket 去读取客户端的请求命令,而是先将 client 放入一个 LIFO 队列 clients_pending_read
  5. 在事件循环(Event Loop)中,主线程执行 beforeSleep -->handleClientsWithPendingReadsUsingThreads,利用 Round-Robin 轮询负载均衡策略,把 clients_pending_read队列中的连接均匀地分配给 I/O 线程各自的本地 FIFO 任务队列 io_threads_list[id] 和主线程自己,I/O 线程通过 socket 读取客户端的请求命令,存入 client->querybuf 并解析第一个命令,但不执行命令,主线程忙轮询,等待所有 I/O 线程完成读取任务;
  6. 主线程和所有 I/O 线程都完成了读取任务,主线程结束忙轮询,遍历 clients_pending_read 队列,执行所有客户端连接的请求命令,先调用 processCommandAndResetClient 执行第一条已经解析好的命令,然后调用 processInputBuffer 解析并执行客户端连接的所有命令,在其中使用 processInlineBuffer 或者 processMultibulkBuffer 根据 Redis 协议解析命令,最后调用 processCommand 执行命令;
  7. 根据请求命令的类型(SET, GET, DEL, EXEC 等),分配相应的命令执行器去执行,最后调用 addReply 函数族的一系列函数将响应数据写入到对应 client 的写出缓冲区:client->buf 或者 client->reply ,client->buf 是首选的写出缓冲区,固定大小 16KB,一般来说可以缓冲足够多的响应数据,但是如果客户端在时间窗口内需要响应的数据非常大,那么则会自动切换到 client->reply 链表上去,使用链表理论上能够保存无限大的数据(受限于机器的物理内存),最后把 client 添加进一个 LIFO 队列 clients_pending_write
  8. 在事件循环(Event Loop)中,主线程执行 beforeSleep --> handleClientsWithPendingWritesUsingThreads,利用 Round-Robin 轮询负载均衡策略,把 clients_pending_write 队列中的连接均匀地分配给 I/O 线程各自的本地 FIFO 任务队列 io_threads_list[id] 和主线程自己,I/O 线程通过调用 writeToClient 把 client 的写出缓冲区里的数据回写到客户端,主线程忙轮询,等待所有 I/O 线程完成写出任务;
  9. 主线程和所有 I/O 线程都完成了写出任务, 主线程结束忙轮询,遍历 clients_pending_write 队列,如果 client 的写出缓冲区还有数据遗留,则注册 sendReplyToClient 到该连接的写就绪事件,等待客户端可写时在事件循环中再继续回写残余的响应数据。

这里大部分逻辑和之前的单线程模型是一致的,变动的地方仅仅是把读取客户端请求命令和回写响应数据的逻辑异步化了,交给 I/O 线程去完成,这里需要特别注意的一点是:I/O 线程仅仅是读取和解析客户端命令而不会真正去执行命令,客户端命令的执行最终还是要在主线程上完成

数据库mysql

        mysql执行过程

  • MySQL客户端通过协议将SQL语句发送给MySQL服务器。
  • 服务器会先检查查询缓存中是否有执行过这条SQL,如果命中缓存,则将结果返回,否则进入下一个环节(查询缓存默认不开启)。
  • 服务器端进行SQL解析,预处理,然后由查询优化器生成对应的执行计划。
  • 服务器根据查询优化器给出的执行计划,再调用存储引擎的API执行查询。
  • 将结果返回给客户端,如果开启查询缓存,则会备份一份到查询缓存中。

        sql执行顺序

         mysql事务

1. MySQL InnoDB Mysaim 的特点?
a. InnoDB
        1. ⽀持事务处理
        2. ⽀持外键
        3. ⽀持⾏锁
        4. 不⽀持 FULLTEXT 类型的索引(在 Mysql5.6 已引⼊)
        5. 不保存表的具体⾏数,扫描表来计算有多少⾏
        6. 对于 AUTO_INCREMENT 类型的字段,必须包含只有该字段的索引
        7. DELETE 表时,是⼀⾏⼀⾏的删除
        8. InnoDB 把数据和索引存放在表空间⾥⾯
        9. 跨平台可直接拷⻉使⽤
        10. 表格很难被压缩

表空间 - > 段 256m ->区 1m -> 页 16k

独立表空间

段包括数据段,索引段,回滚段


b. MyISAM
        1. 不⽀持事务,回滚将造成不完全回滚,不具有原⼦性
        2. 不⽀持外键
        3. ⽀持全⽂搜索
        4. 保存表的具体⾏数,不带 where 时,直接返回保存的⾏数
        5. DELETE 表时,先 drop 表,然后重建表
        6. MyISAM 表被存放在三个⽂件 。 frm ⽂件存放表格定义。 数据⽂件是 MYD ( MYData)         。 索引⽂件是MYI
        (MYIndex )引伸
        7. 跨平台很难直接拷⻉
        8. AUTO_INCREMENT 类型字段可以和其他字段⼀起建⽴联合索引
        9. 表格可以被压缩
c. 选择:因为 MyISAM 相对简单所以在效率上要优于 InnoDB. 如果系统读多,写少。对原⼦性要求低。那么 MyISAM 最好
的选择。且 MyISAM 恢复速度快。可直接⽤备份覆盖恢复。如果系统读少,写多的时候,尤其是并发写⼊⾼的时候。
InnoDB 就是⾸选了。两种类型都有⾃⼰优缺点,选择那个完全要看⾃⼰的实际类弄。
myisam查询为什么比innodb快

1)数据块,InnoDB要缓存,MyISAM只缓存索引块,  这中间还有换进换出的减少;

2)InnoDB寻址要映射到块,再到行,MyISAM记录的直接是文件的OFFSET,定位比InnoDB要快

3)InnoDB还需要维护MVCC一致; 虽然你的场景没有,但他还是需要去检查和维护

2. MySQL事务四大特性
原子性,隔离性,一致性,持久性
3数据库隔离级别是什么?有什么作⽤?
读未提交
读已提交
可重复读
串行化
mysql事务底层mvcc

        mysql索引

索引类型

Mysql目前主要有以下几种索引类型:FULLTEXT,HASH,BTREE,RTREE。

索引种类

普通索引

主键索引 

唯一索引 可以有null

联合索引

全文索引

索引失效场景

索引一定不是越多越好,越全越好,一定是建合适的。
匹配列前缀可用到索引 like 9999%,like %9999%、like %9999用不到索引;
Where 条件中 not in 和 <>操作无法使用索引;
匹配范围值,order by 也可用到索引;
多用指定列查询,只返回自己想到的数据列,少用select *;
联合索引中如果不是按照索引最左列开始查找,无法使用索引;
隐式转换和函数

查询数据据量多,导致全表扫描

mysql锁

a. ⾏锁:数据库表中某⼀⾏被锁住。
b. 表锁:整个数据库表被锁住。
c. 乐观锁:顾名思义,就是很乐观,每次去拿数据的时候都认为别⼈不会修改,具体实现是给表增加⼀个版本号的字
段,在执⾏ update 操作时⽐较该版本号是否与当前数据库中版本号⼀致,如⼀致,更新数据,反之拒绝。
d. 悲观锁:顾名思义,就是很悲观,每次去拿数据的时候都认为别⼈会修改。读数据的时候会上锁,直到 update 完成才
释放锁,使⽤悲观锁要注意不要锁住整个表。
mvcc机制
什么是MySQL的MVCC机制? - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/367820387#:~:text=%20MVCC%E6%9C%BA%E5%88%B6%E7%9A%84%E4%BD%9C%E7%94%A8%E5%85%B6%E5%AE%9E%E5%B0%B1%E6%98%AF%E9%81%BF%E5%85%8D%E5%90%8C%E4%B8%80%E4%B8%AA%E6%95%B0%E6%8D%AE%E5%9C%A8%E4%B8%8D%E5%90%8C%E4%BA%8B%E5%8A%A1%E4%B9%8B%E9%97%B4%E7%9A%84%E7%AB%9E%E4%BA%89%EF%BC%8C%E6%8F%90%E9%AB%98%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%B9%B6%E5%8F%91%E6%80%A7%E8%83%BD%E3%80%82%20%E5%85%81%E8%AE%B8%E5%A4%9A%E4%B8%AA%E7%89%88%E6%9C%AC%E5%90%8C%E6%97%B6%E5%AD%98%E5%9C%A8%EF%BC%8C%E5%B9%B6%E5%8F%91%E6%89%A7%E8%A1%8C%E3%80%82,%E4%B8%8D%E4%BE%9D%E8%B5%96%E9%94%81%E6%9C%BA%E5%88%B6%EF%BC%8C%E6%80%A7%E8%83%BD%E9%AB%98%E3%80%82%20%E5%8F%AA%E5%9C%A8%E8%AF%BB%E5%B7%B2%E6%8F%90%E4%BA%A4%E5%92%8C%E5%8F%AF%E9%87%8D%E5%A4%8D%E8%AF%BB%E7%9A%84%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E4%B8%8B%E5%B7%A5%E4%BD%9C%E3%80%82%20%E5%9C%A8%E6%97%A9%E6%9C%9F%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%AD%EF%BC%8C%E5%8F%AA%E6%9C%89%E8%AF%BB%E8%AF%BB%E4%B9%8B%E9%97%B4%E7%9A%84%E6%93%8D%E4%BD%9C%E6%89%8D%E5%8F%AF%E4%BB%A5%E5%B9%B6%E5%8F%91%E6%89%A7%E8%A1%8C%EF%BC%8C%E8%AF%BB%E5%86%99%EF%BC%8C%E5%86%99%E8%AF%BB%EF%BC%8C%E5%86%99%E5%86%99%E6%93%8D%E4%BD%9C%E9%83%BD%E8%A6%81%E9%98%BB%E5%A1%9E%EF%BC%8C%E8%BF%99%E6%A0%B7%E5%B0%B1%E4%BC%9A%E5%AF%BC%E8%87%B4MySQL%E7%9A%84%E5%B9%B6%E5%8F%91%E6%80%A7%E8%83%BD%E6%9E%81%E5%B7%AE%E3%80%82

索引优化

 - 查看表结构    
    desc table_name;
 - 查看生成表的SQL    
    show create table table_name;
 - 查看索引    
    show index from  table_name;
 - 查看执行时间    
    set profiling = 1;    
    SQL...    
    show profiles;
 - explain查询计划
    id:选择标识符
    select_type:表示查询的类型。 simple,union,primary,subquery,dependent subquery
    table:输出结果集的表
    partitions:匹配的分区
    type:表示表的连接类型 ref,const,eq_ref,system,range
    possible_keys:表示查询时,可能使用的索引 
    key:表示实际使用的索引
    key_len:索引字段的长度
    ref:列与索引的比较
    rows:扫描出的行数(估算的行数)
    filtered:按表条件过滤的行百分比
    Extra:执行情况的描述和说明
 - 慢查询日志
    --查询配置命令
    show variables like '%query%';
    --当前配置参数
        binlog_rows_query_log_events    OFF
        ft_query_expansion_limit    20
        have_query_cache    YES
    --时间限制,超过此时间,则记录
        long_query_time    10.000000
        query_alloc_block_size    8192
        query_cache_limit    1048576
        query_cache_min_res_unit    4096
        query_cache_size    1048576
        query_cache_type    OFF
        query_cache_wlock_invalidate    OFF
        query_prealloc_size    8192
    --是否开启慢日志记录
        slow_query_log    OFF
    --日志文件
        slow_query_log_file    D:\mysql-5.7.18-winx64\data\Jack-slow.log
    --看慢查询sql
    mysqldumpslow -s c -t 10 /var/run/mysqld/mysqld-slow.log # 取出使用最多的10条慢查询

消息队列kafka

Kafka 概述:深入理解架构 - 知乎 (zhihu.com)icon-default.png?t=N6B9https://zhuanlan.zhihu.com/p/103249714

运维相关

nginx配置 反向代理和负载均衡
       

        location /backstage {
            alias   /home/dispatch/ui;
            try_files $uri $uri/ /backstage/index.html;
            index  index.html index.htm;
        }
       
        location /article.html {
            root   /home/dispatch;
            index  article.html;
            try_files $uri $uri/ /article.html;
        }
        location /stage-api/ {
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header REMOTE-HOST $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            rewrite  ^/stage-api/code$ /code break;
            proxy_pass http://172.21.105.252:8080/;
        }

skywalking

        https://www.yuque.com/yulal/noaqkm/mfycaknfd2moetss

        链路追踪

        服务拓扑

        cpu资源

        服务监控

        日志查看

        服务告警

        

当然,我可以帮你复习Java基础面试题。以下是一些常见的Java基础面试题及其答案: 1. Java中的基本数据类型有哪些? 答:Java中的基本数据类型包括byte、short、int、long、float、double、boolean和char。 2. Java中的包装类是什么? 答:包装类是一种将基本数据类型封装成对象的方式。Java提供了对应于每个基本数据类型的包装类,如Integer、Double、Boolean等。 3. Java中的String类是可变的吗? 答:String类是不可变的,即一旦创建就不能被修改。如果需要对字符串进行修改操作,可以使用StringBuilder或StringBuffer类。 4. Java中的final关键字有什么作用? 答:final关键字可以用来修饰类、方法和变量。当修饰类时,表示该类不能被继承;当修饰方法时,表示该方法不能被重写;当修饰变量时,表示该变量的值不能被修改。 5. Java中的抽象类和接口有什么区别? 答:抽象类是一种不能被实例化的类,它可以包含抽象方法和非抽象方法。接口是一种完全抽象的类,它只能包含抽象方法和常量。一个类可以实现多个接口,但只能继承一个抽象类。 6. Java中的异常处理机制是什么? 答:Java中的异常处理机制通过try-catch-finally语句块来实现。当可能发生异常的代码放在try块中,如果发生异常,则会被catch块捕获并进行处理,最后无论是否发生异常,都会执行finally块中的代码。 7. Java中的多线程是如何实现的? 答:Java中实现多线程有两种方式,一种是继承Thread类,另一种是实现Runnable接口。通过重写Thread类的run()方法或实现Runnable接口的run()方法来定义线程的执行逻辑。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值