赞
踩
多数企业招聘要求如下:
注:mq、设计模式、nginx、通信协议
1111:高频
2222:重点
3333:注意
常考:Java集合、面向对象;MySQL、Redis;了解JVM(垃圾回收、内存运行区域);计网
1. java八大基本数据类型
byte short int long float double char boolean
2. JDK JRE JVM
JDK: java开发工具包(包含java编译器、JRE);编写、编译、调试、运行
JRE: java运行环境;提供运行环境
JVM(java虚拟机): java程序执行的核心组件;将java源码编译成字节码、运行时解析执行字节码。内存管理
3. 栈和堆
栈:后进先出;存储函数调用时的参数、局部变量、返回地址等数据
堆:先进先出、是树形结构;存储动态分配的内存,如new出来的对象、数组
4. 异步、同步调用
指不同组件之间的调用方式
同步调用:程序的运行会阻塞,等待被调用组件的响应结果。
异步调用:程序的运行不会被阻塞,可以同时执行多个调用操作。
5. 并行和并发
并行:两个或多个事件同一时刻进行
并发:两个或多个事件同一时间间隔发生
6. 深浅拷贝
对于基础数据类型:直接复制数据值
浅拷贝:只复制对象的值,不复制它所引用的对象;新旧对象共享同一个引用对象。
(会改变原始数据)
深拷贝:复制对象本身和所有它所引用的对象;新旧对象不共享任何引用对象。
(不会改变,创建新的)
7. “==” 和equals()的区别
== 比较的是两个对象的引用是否一致(是否指向同一个内存地址);如果是基本数据类型,比较的是值是否相等。
equals()比较的是两个对象的内容是否相等(默认调用 ==,但通过覆盖方法)。
8. 重载和重写的区别
重载:是一个类下多个同名的方法。方法的参数类型、个数、顺序可不同;(返回值不同)
重写:在子类中,定义与父类同名、参数类型和返回值类型相同的方法(重写父类方法)
9. Java 三大特性
面向对象编程、平台无关性(可在不同操作系统运行)、安全性
10. 面向对象三大特性
封装、继承、多态
封装:数据和方法捆绑在一起;实现对数据的保护
(隐藏对象的内部细节,提供公共访问接口;提高代码的安全性和可维护性)
继承:子类可继承父类的属性和方法;避免重复编写代码
多态:方法根据不同的参数类型和数量而表现出不同的行为;提高代码复用性和灵活性(ps: 子类对对象可代替父类对象出现的位置,并可调用父类的方法,这个方法是经过重载、重写)
11. Final,
修饰类:不能被继承;修饰方法:不能被重写/覆盖,可以继承和调用
12. This和super
This:首先访问本类,没有则访问父类(子->父)
Super:访问父类的属性或方法
13. Java类只能继承一个父类(一个父亲)、可实现多个接口(单继承、多实现)
14. 抽象类(abstract class)和接口的区别
抽象类只能单继承;接口可以多实现(单继承、多实现)
抽象类有构造方法(类有构造方法);接口没有
抽象类有成员变量;接口没有,只有常量
抽象类有抽象和非抽象方法;接口只有抽象方法
抽象类是自下而上抽象;接口是自上而下抽象
ps: 构造方法:创建对象时调用,初始化对象;成员方法,对象调用;抽象方法,继承或实现,重写方法,对象调用
15. 访问权限修饰
16.自动装箱和自动拆箱
自动装箱:将基本数据类型转换为包装类对象
自动拆箱:将包装类对象转为基本数据类型
17. 抽象方法没有方法体,只有方法的声明没有具体的方法实现
18. String
用于处理字符串的类
String常用方法:
split():分割,比如以“,”进行分割
charAt:获取指定位置字符
length():空格也算一个字符
isEmpty()
19. 简述String、 StringBuilder、StringBuffer
String: 其值不可修改;除非新建对象,将新老字符一并存进去
StringBuider:其值可修改,线程不安全
StringBuffer: 其值可修改,线程安全
20. java中只有值传递
21. 阐述 final、finally的区别
final:
修饰类:该类不能派生子类,不能被继承
修饰方法:该类不能被子类重写
修饰变量:需在声明时给定初始值,只能读取,不可修改;如果对象是变量,指引用不可修改,对象的属性不可修改
finally:
搭配try catch使用,无论是否出现异常都一定执行的代码
22. get和post的区别
get | post |
向服务器获取数据 | 向服务器提交数据 |
数据放在URL地址之后 | 数据放在请求体(request body)中 |
不安全,不适合传递敏感信息 | 安全,适合传递敏感信息 |
Get请求可被缓存 | post请求不可缓存 |
产生一个tcp数据包 | 产生两个tcp数据包 |
1. 反射是指在程序运行时动态获取类的信息并操作类的属性、方法和构造器,以及创建对象实例的能力
可通过以下类调用反射API:
Class类:可获得类属性方法
Field类:获得类的成员变量
Method类:获得类方法信息
Construct类:获得类构造方法信息
javaIO:读写数据模块。提供一组类和接口,对文件读写和网络通讯的操作.
1. 字节流和字符流
字节流:用来处理二进制数据(图像、音、视频)
字符流:用于处理文本数据
2. bit、byte、char的区别
bit:最小二进制单位
byte:存储数据的单位
char:最小读写单位
常见的集合:
List:有序集合,元素可重复,用collections.sort()对List进行排序(常见实现类(子类)有ArrayList、LinkedList)
Set:无序集合,元素不可重复;可用作字符串去重(HashSet、TreeSet、 LinkedHashSet)
Map:键值对(HashMap、TreeMap、LinkedHashMap 和 Hashtable)
Queue:队,先进先出
Stack:栈,后进先出
1. List和set的区别
List: 有序,可重复
Set: 无序,不可重复
2. ArrayList和LinkedList的区别
ArrayList: 采用数组实现,可随机访问,插入和删除性能不好(移动元素)
LinkedList:采用双向链表实现,不可随机访问,插入和删除性能好
3. 数组与ArrayList的区别
类型 | 数组 | ArrayList |
存放类型 | 基本类型、对象 | 对象 |
内存大小 | 固定,初始化指定 | 动态大小 |
数据存放 | 连续存放 | 对象的引用是连续,对象本身在内存中不一定连续 |
插入与删除 | 不能添加和删除 | 可以在任意位置出入和删除 |
效率 | 高 | 低 |
4. ArrayList扩容机制
当执行add()操作时,容量不足,行扩容:
(1)计算新的容量,一般是当前容量的1.5倍
(2)创建新的数组,其长度为新的容量,把当前数组的元素复制到新的数组
(3)更新容量和数组引用
扩容涉及到数组复制和重新分配内存,引起性能开销。为尽量避免扩容,可在创建时指定初始容量。
5. List去重/排序
- public static List<Integer> stream (List<Integer> list){
- return list.stream().distinct().collect(Collectors.toList());
- }
- public static List<Integer> HashSet (List<Integer> list) {
- HashSet<Integer> h = new HashSet<>(list);
- return new ArrayList<>(h);
- }
Map(接口)一种映射关系(key、value)。Map接口有多个实现类(子类),其中最常用的是HashMap、TreeMap和LinkedHashMap。
1. HashMap、TreeMap、LinkedHashMap的区别
类型 | HashMap | TreeMap | LinkedHashMap |
按插入顺序排放 | 不支持 | 不支持 | 支持 |
按key排序 | 不支持 | 支持,默认按key升序排序 | 不支持 |
数据结构 | 数组+链表+红黑树 | 红黑树 | HashMap+双向链表 |
Kv值 | 只允许一条key的值为null;允许多条value的值为null | 不允许key的值为null | 同HashMap |
8. HashMap
实现:
JDK<1.8,数组+链表;JDK>1.8,数组+链表+红黑树
当链表长度大于8,数组长度大于等于64,自动升级为红黑树;红黑树节点小于6,红黑树转为链表
解决冲突:链地址法(JDK7是头插法;JDK8是尾插法)
9. collection和collections的区别
collections是一个工具类,在java.util中。它提供一些列的静态方法包括排序、查找、
同步等,用于操作集合对象
Eg: List<String> myList = new ArrayList<>();
myList.add("Apple");
myList.add("Orange");
Collections.sort(myList);
1. 线程的六种状态
2. 实现多线程的三种方式(一个类,两个接口)
a.继承Thread类(重写run方法)
b.实现Runnable接口(重写run方法)
c.实现Callable接口(重写call方法)
3. 停止线程方法
1. stop方法,强制结束(方法已经过时)
让线程的run方法结束来停止线程:
2. 使用共享变量(声明一个共享变量(flag),根据变量的值(flag=true)来判断并结束线程)(全局)
3. 使用interrupt方法(改变interrupt的状态(true/false))(线程内部)(推荐使用)
4. sleep() 和 wait() 有什么区别?ip
用于暂停线程
类的不同:sleep()来自Thread类;wait()来自Object类(任何对象皆可调用)
释放锁:sleep()不会释放锁(睡着了);wait()会释放锁(等待久了就会放弃)
用法不同:sleep()时间到会自动恢复;wait()可用notify()\notifyAll()手动唤醒
对用转态:sleep属于TIME_WAITING;wait属于WAITING
sleep暂停线程、但监控状态仍然保持,结束后会自动恢复
5. 什么是死锁,如何避免
是指两个或多个事务相互等待对方释放资源下,无法继续执行的状态
避免死锁:
6. 项目哪些地方用到多线程
定时任务:定时处理数据进行统计
异步处理:发邮件、发短信、记录日志
批量处理,缩短响应时间
7. JMM
所有变量都存储在主内存
所有线程都有自己的工作内存,保存了使用到变量的主内存的副本拷贝
线程对变量的操作均在工作内存中(先拷贝到工作内存->操作->写回主内存)
不同线程不能直接访问对方工作内存的变量,线程之间值的传递通过主内存完成
JMM三大特性:
原子性:一个或多个操作在执行过程不被中断
可见性:一个线程对共享变量的修改,另一个线程能立即看到
有序性:程序执行的顺序按代码的先后顺序执行
Happens-before八大原则
程序顺序原则:按程序顺序执行
锁原则:先解锁后加锁
Volatile变量原则:volatile变量的写发生在读之前,保证volatile变量的可见性
线程启动原则:线程的start()方法先于他的每一个操作
传递性原则
线程终止原则:线程的所有操作先于线程的终止
线程中断原则:中断方法interrupt()先于监测发生线程中断的方法interrupted()方法
对象终结原则:对象构造函数执行的结束,先于finalize()方法
Synchronized的作用
保证原子性、有序性、可见性
Volatile的作用
保证有序性、可见性,不保证原子性
8. 为什么使用线程池
没有线程池情况下,多次创建、销毁线程开销较大。如果开辟的线程执行完当前任务后不销毁,之后的任务可以复用已创建的线程,可以降低开销,控制最大并发数。
优点:降低资源消耗、提高响应速度、提高线程的可管理性
缺点:1.多线程会占用CPU
9. 线程池本身的缺点:
a.适用于生存周期较短的任务
b.不能对线程池的任务设置优先级
c.不能表示线程的各个状态(如启动、终止线程)
d. ...
10. 线程池的参数
1. corePoolSize:常驻核心线程数
2. maximumPoolSize:最大线程数
3. keeyAliveTime:线程存活时间,达到该时间后线程会被销毁,直到corePoolSize个线程
4.workQueue:工作队列,提交的任务会被放到这个队列里
5.threadFactory:线程工厂,用来创建线程
6.handler:拒绝策略。当线程池里线程被耗尽,队列也满时会被调用;默认拒绝策略AbortPolicy,丢弃任务并抛出运行异常
11. 拒绝策略的类型(饱和策略)
AbortPolicy:丢弃任务并抛出异常
CallerRunsPolicy:重新尝试提交该任务
DiscardPolicy:直接抛弃当前任务但不抛出异常
DiscardOldestPolicy:抛弃队列里等待最久的任务并把当前任务加入队列
12. 阻塞队列
ArrayBlockingQueue:底层时由数组组成的有界阻塞队列
LinkedBlockingQueue:底层时由链表组成的有界阻塞队列
PriorityBlockingQueue:阻塞优先队列
DelayQueue:
SynchronousQueue
。。。
13. 线程池执行流程
14. 线程池状态
Running:正常运行,既能接受新任务,也会处理队列中的任务
ShutDown:不接受新任务,但能处理已添加的任务
Stop:不接受新任务,也不处理已添加的任务,终止正在处理的任务
Tidying:线程池没有任务在执行,会进入Tidying状态
Terminated:调用terminated()后,线程池彻底终止时进入的状态
Juc
15. 简述Lock与ReentrantLock
Lock时Java并发包的顶层接口
ReentrantLock是Lock接口的一个实现类,与synchronized 一样是可重入。ReentrantLock默认情况是非公平的,也可使用构造方法指定公平。一旦使用公平锁,性能下降
16. CAS
CAS是一种乐观锁
CAS原理:
从内存中读取当前值(预期值)
预期值与内存中实际值进行比较
若相等,表示其他线程没有修改该值,进行更新操作;若不等,表示已经修改,更新失败,重新尝试。
优点:性能高(一直自旋等待锁)
缺点:CPU开销大
ABA问题:一个值原来是A,然后变成B,最后又变成A,CAS会认为他没有变
能保证一个共享变量原子操作:要保证多个时,要使用Synchronized
17. AQS
18. ynchronized与volatile
Ynchronized:
锁定的对象,只有当前线程可以访问,其他线程阻塞
使用范围:变量、方法、类
可以保证变量的可见性、原子性;可能造成线程阻塞;标记的变量可以被编译器优化
Volatile:
本质是告诉jvm当前变量在工作内存的值是不确定的,需要从主内存中读取
使用范围:变量
仅能实现变量的可见性;不会造成线程阻塞;标记的变量不会被编译器优化
19. synchronized 和 Lock 有什么区别?
类型 | synchronized | Lock |
使用范围 | 可给类、方法、代码块加锁 | 只能给代码块加锁 |
获取/释放方式 | 不需要手动获取锁和释放锁 | 需要自己手动加锁和释放锁 |
是否会死锁 | 发生异常会自动释放锁,不会造成死锁 | 如果不用unlock释放锁会造成死锁 |
属性 | java内嵌关键字,在jvm层面 | Java类(接口) |
判断是否获得锁 | 无法判定 | 可以判定 |
20. 线程池创建方法
1. newFixedThreadPool:创建固定大小线程池。
2. newSingleThreadExecutor:单线程线程池
3. newCachedThreadPool:可缓存线程池,maximumPoolSize
4. newScheduleThreadPool:定时线程池
5. newWorkStealingPool:拥有多个任务的线程池
JVM内存模型
用于描述JVM如何管理内存以支持java程序执行的规范
JVM定义的内存区域:
(1)线程共享数据区:
方法区:类信息(被虚拟机加载过)、静态变量、常量(被Final修饰)
堆:(new)对象实例、数组。堆又分为新生代和老年代
(2)线程隔离数据区:
栈/虚拟机栈(Stack/VM Stack): 基本类型和引用类型(String)的变量;存储方法调用的局部变量、操作数栈、方法的返回值
本地方法栈:存储java调用本地方法(Native方法)的相关数据(根栈是一样的)
程序计数器(Program Counter Register):保存当前线程执行的字节码指令地址;不会发生内存泄露
1. JVM类加载过程
1.加载:
通过全类名获取类的二进制字节流
将类的静态存储结构转化为方法区运行时数据结构
在内存中生成类的Class对象,作为方法区数据入口
2.验证:检查载入的class文件数据的正确性
3.准备:在方法区为类变量分配内存并设置为零值
4.解析:将常量池内的符号引用转换为直接引用
5.初始化:初始化类静态变量,执行静态语句块
2. JDK8垃圾回收器流程(内存管理)
JDK8内存模型
垃圾收集流程:
1. new一个对象时,首先保存在Eden区,前提判断Eden空间是否充足
空间足够:在Eden区为新对象申请空间
空间不够:执行MinorGC(年轻代GC)
2. MinorGC会回收不活跃对象,释放Eden间,接着再判断空间是否充足
空间足够:在Eden区为新对象申请内存空间
空间不够:将部分活跃对象保存在Survivor区
3. Survivor空间也要先判断是否充足
空间足够:保存Eden发来的对象。此时Eden空间得以释放,在Eden区为新对象申请空间
空间不够:将Survivor区部分活跃对象保存在Tenured区
4. 依然要判断Tenured空间是否充足
空间足够:保存Survivor发来的对象,在Eden区为新对象申请空间
空间不够:将执行FullGC(完全GC),以释放年轻代和老年代中保存的不活跃对象。
5. 执行FullGC后再次判断Tenured区空间
空间足够:保存Survivor发来的对象,Survivor也会保存Eden发来的对象,然后就可以在Eden区为新对象申请空间
空间不够:抛出OutOfMemoryError(OOM),程序将中断运行
3. Java引用类型
强引用:这个对象永远不会被回收,即使内存不足;使用new方法创建
(User user = new User() )
软引用:只有内存不足时,JVM才会回收该对象
弱引用:不管内存是否充足,只要发生GC,弱引用就会被回收
虚引用:无法通过虚引用获取一个对象的真实引用
4. Young GC(Minor GC)
多数情况,对象在年轻代中的Eden区进行分配,若Eden没有足够的空间,就会触发YGC
5. Full GC(Major GC)
FGC处理的区域包括年轻代和老年代
以下会触发Full GC:
1.老年代使用率达到了一定阈值(默认92%)
2.元空间扩容到指定值
3.程序执行了System.gc():只是提醒JVM执行Full GC,不一定执行
6. CMS与G1的区别
7. JVM调优的常用配置
-Xms:初始堆大小
-Xmx:最大堆大小
-Xmn /-XX:NewSize:年轻代大小
-XX:MaxNewSize:年轻代最大值
-XX:PermSize:老年代/永生代初始值
-XX:MaxPermSize:老年代/永生代最大值
-XX:NewRatio:新生代与老年代的比例
1. SQL优化你了解哪些?
a. 避免全表扫描: 在没有索引的情况,对整个表进行扫描;应该使用索引来查询
b. 避免使用select * (查询所有列):指定所需的列可以减少数据传输量和查询时间
c. 避免使用子查询(嵌套查询):子查询会增加数据库的负担,导致性能下降
d. 使用join代替子查询:join可将多个查询合并为一个查询,减少数据库的负担
e. 避免使用where子句中的函数:会对整个表进行计算,导致性能下降
f. 避免使用order by 中的函数:会对整个结果集进行计算,导致性能下降
g. 使用explain命令分析查询计划: explain命令可查看查询执行计划,从而确定哪部分需要优化
总之,SQL优化是一个综合性的过程,需要综合考虑多个因素。通过合理的SQL编写和优化,可以提高数据库的性能和效率。
2. Mysql日志你了解哪些,有什么作用?
a. 二进制日志(Binary Log): 记录了MySQL数据库所有的增删改操作;用于主从复制、数据备份和恢复等场景
b. 慢查询日志(Slow Query Log):记录执行时间超过指定阈值的SQL语句
c. 错误日志(Erroy Log):记录 SQL运行时的发生的错误信息,如连接问题、权限问题
3. 针对一条慢 SQL,通常会怎样去优化它?
a. 优化SQL语句
b. 添加索引:对经常被查询的列建立索引
c. 分页查询:对于数据量比较大的表,使用分页避免一次性查询所有的数据,从而减少查询时间
d. 缓存结果集:对于一些计算复杂的SQL语句,将查询结果缓存起来,避免重复计算
e. 调整服务器配置:若以上都无法解决问题,可增加内存、优化硬盘读写等方式提高数据库性能
在进行SQL语句优化时,需要综合考虑多个因素,包括数据量、查询频率、硬件配置等等。
4. 数据库的基本属性
ACID是数据库系统中的四个基本属性,用于描述事务的正确性、一致性、隔离性、持久性。
原子性(A):保证事务中的所有操作要么全部成功,要么全部失败回滚
一致性(C):保证事务执行前后,数据库应保持一致性状态,避免数据的不一致性
隔离性(I):多个事务操作同一数据时,事务之间相互隔离(一个事务执行不被其他事务干扰)
持久性(D):一旦事务提交,对数据的修改应该是永久性的,即使系统发生故障或崩溃也不会丢失
5. 索引失效的情景
LIKE以 % 或 _ 开头
OR语句前后没有同时使用索引
联合索引没有遵循最左前缀原则
索引列数据类型出现隐式转换
对索引列进行计算或使用函数
ORDER BY 使用错误
全表扫描速度比索引速度快
6. 事务的隔离级别(级别越高,数据一致性越强,并发性能越低)
1.读未提交:允许事务读取未提交(修改但未持久化)的数据;存在脏读、不可重复读和幻读(最低隔离级别)
2.读已提交:只允许读取已提交的事务;存在不可重复读、幻读(多数数据库默认隔离级别)
3.可重复读:同一条件的查询返回的结果是一样的 ;存在幻读(MySQL默认隔离级别)
4.可串行化:(最高隔离级别)强制所有事务以串行方式执行;解决所有并发问题,但导致性能下降
7. 脏读、幻读、不可重复读
脏读:读取了一个事务未提交的数据(未持久化),这个数据在后续的事务执行中可能会修改或删除
幻读:事务在执行中,两次查询相同条件的数据,返回了第一次查询未返回的新数据,这是因为其他事务插入的新的数据
不可重复读:事务在执行时,两次读取了同一个数据的结果不一致,因为另一个事务对其进行修改或删除
8. MySQL索引的优点、缺点
优点:
提高查询效率;改善排序性能;优化分组操作;支持范围查询(eg: 大于、小于)
缺点:
降低数据写入效率;增加了查询优化器的选择时间;占物理空间
9. 创建索引的原则
对查询频率高的字段创建索引
为经常需要排序、分组和联合操作的字段建立索引
尽量使用唯一以索引
使用短索引
使用前缀来索引
索引的数目不要太多
避免索引失效
10.drop delete truncate的区别
Drop: 删除数据库中的对象(如:表、索引等)
Delete: 删除表中的数据行,可回滚撤销删除
Truncate:快速删除表中的所有数据,不可回滚数据
11. 四大范式
第一范式:数据库中每个字段都是不可分割的原子数据项
第二范式:在1NF基础上,非主键列完全依赖于主键(通过主键唯一确定非主键列数据)
第三范式:在2NF基础上,非主键列之间不应该存在传递依赖关系的(通过另一个与主键依赖)
第四范式:在3NF基础上,复合关键字(多个属性组成的候选键或主键)之间不能存在函数依赖关系
12. 段式存储:将内存划分为若干个段
访问段式存储地址需要:段号和段内地址(偏移)
13. Left join 和 right join 的区别
Left join:
以左为主,关联上右边表的数据,显示左边所有的数据,右边显示的是与左边有交集部分的数据
select *
from subject
left join score on subject.id = score.id
right join:
以右为主,显示出右边所有的数据,左边显示的是与右边有交集部分的数据
1. GROUP BY:对一个或多个列的结果集进行分组
mysql> SELECT name, COUNT(*) FROM employee_tbl GROUP BY name;
+--------+----------+
| name | COUNT(*) |
+--------+----------+
| 小丽 | 1 |
| 小明 | 3 |
| 小王 | 2 |
+--------+----------+
2. 基础语句
增删改查:
SELECT **, ** FROM 表WHERE ** = ‘**’
INSERT INTO 表 (**, **) VALUES (‘*’,’*’)
UPDATE表SET ** = ‘**’ WHERE ** = ‘**’
DELETE FROM 表 WHERE ** = ‘**’
连接:LEFT、RIGHT、FULL、INNER同样
SELECT **, **
FROM 表1 a
LEFT JOIN 表2 b ON b.a_id = a.id
排序ORDER BY:ASC升序 DESC降序
SELECT *
FROM 表
ORDER BY id DESC
分组GROUP BY:按名字分组,每个名字出现多少次
SELECT name, count(*)
FROM 表
GROUP BY name
3. 查询部门最高工资的员工信息
(1)建表:
CREATE TABLE t_department (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100)
);
CREATE TABLE t_employee (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100),
salary DECIMAL(10, 2),
department_id INT,
FOREIGN KEY (department_id) REFERENCES t_department(id)
);
(2)填数据:
INSERT INTO t_department VALUES (1, 'IT');
INSERT INTO t_department VALUES (2, 'Sales');
INSERT INTO t_employee VALUES (1, 'joe', 7000.00, 1);
INSERT INTO t_employee VALUES (2, 'henry', 8000.00, 2);
INSERT INTO t_employee VALUES (3, 'sam', 6000.00, 2);
INSERT INTO t_employee VALUES (4, 'tony', 9000.00, 1);
(3)查询部门最高工资的员工信息:
SELECT e.name as employee, e.salary as salary, d.name department
FROM t_employee e
JOIN t_department d on e.department_id = d.id
JOIN (
SELECT max(salary) as max_salary, department_id
FROM t_employee em
GROUP BY em.department_id
) as t_max_salary on e.department_id = t_max_salary.department_id
and e.salary = t_max_salary.max_salary
1. Redis使用场景
Redis是一种高性能的内存 键值存储数据库
缓存:将常用的数据缓存到内存中,提高访问速度
消息队列:支持“发布-订阅”模式,可作为轻量级消息队列使用
计数器:可实现计数器功能
排行榜:支持对不同维度的数据进行排名和统计
分布式锁:提供分布锁功能,可实现分布式系统的互斥操作、
基于Redis实现共享session
2. Redis支持的数据类型
String字符串
List列表:是一个双向链表结构
Set集合:无序、不重复;支持交、并、差集等操作
Sorted set有序集合:
Hash哈希表:键值对映射的数据结构;键和值都是字符串类型
以上各个类型的元素都是字符串
3. Redis为什么速度很快
数据存放在内存中
用C语言实现:C语言更底层,执行速度相对更快
使用了多路复用:redis是单线程的,但内部使用了IO多路复用提高性能
作者对代码的精打细磨
4. Redis数据持久化的方式
RDB快照、AOF日记
Redis默认使用的是RDB
RDB:将内存中的数据集转化成二进制文件;代表redis某个时间点上的数据快照;
AOF:将客户端所有写操作记录到一个日志文件;redis重启时,重新执行所有以前的写操作重建数据集
5. Redis缓存穿透如何解决
缓存穿透是指:缓存和数据库均没有要查询的数据,攻击者不断发送这种请求,会击垮数据库
解决1:缓存空对象:当请求数据在Redis缓存中不存在时,直接返回一个空对象
解决2:布隆过滤器:在缓存层和存储层之前,将存在的key用布隆过滤器提前保存起来,做第一层拦截
查询时:
6. Redis缓存雪崩
原因:某个时间点,缓存中大量数据同时失效,请求直接打到数据库
解决:
7. Redis缓存击穿
指一个热点key在失效同时,大量的请求直接访问数据库,会压垮数据库
1. 设计模式
创建者模式(生成器模式):
用于描述怎么创建对象,主要特点是将对象的创建与使用分离
单例、工厂、抽象工厂、创建者、原型模式
结构型(对象)模式:
描述如何将类或对象按照某种布局组成更大的结构
适配器、装饰者、代理、外观、桥接、组合、享元模式
行为型模式
用于描述类和对象之间怎么相互协作共同完成单个对象无法单独完成的任务,以及怎么分配职责
策略、状态、命令、观察者、迭代器、责任链、备忘录、访问者、中介者、解析器、模板方法模式
2. 单例模式
一个类只有一个实例
懒汉模式:懒,只有使用时才创建对象;多线程、懒加载、性能低(加锁同步)
public class Singleton{
private static Singleton instance;
public static synchronized Singleton getInstance(){
if(instance==null){
instance=new Singleton ();
}
return instance;
}
private Singleton (){
}
}
饿汉模式:很饿,类加载时就立即创建对象;多线程、不完全支持懒加载、性能高(非加锁同步)
//对第一行static的一些解释
// java允许我们在一个类里面定义静态类。比如内部类(nested class)。
//把nested class封闭起来的类叫外部类。
//在java中,我们不能用static修饰顶级类(top level class)。
//只有内部类可以为static。
public class Singleton{
//在自己内部定义自己的一个实例,只供内部调用
private static final Singleton instance = new Singleton();
private Singleton(){
//do something
}
//这里提供了一个供外部访问本class的静态方法,可以直接访问
public static Singleton getInstance(){
return instance;
}
}
双重锁的模式
public class Singleton{
private static volatile Singleton instance=null;
private Singleton(){
//do something
}
public static Singleton getInstance(){
if(instance==null){
synchronized(Singleton.class){
if(instance==null){
instance=new Singleton();
}
}
}
return instance;
}
}
//这个模式将同步内容下方到if内部,提高了执行的效率,不必每次获取对象时都进行同步,只有第一次才同步,创建了以后就没必要了。
//这种模式中双重判断加同步的方式,比第一个例子中的效率大大提升,因为如果单层if判断,在服务器允许的情况下,
//假设有一百个线程,耗费的时间为100*(同步判断时间+if判断时间),而如果双重if判断,100的线程可以同时if判断,理论消耗的时间只有一个if判断的时间。
//所以如果面对高并发的情况,而且采用的是懒汉模式,最好的选择就是双重判断加同步的方式。
Servlet拆分为三层
表示层Web(UI)、业务逻辑层service、数据访问层dao
表示层:用于用户交互。数据访问层:与数据库交互,对数据的增删改查。
实体类:数据传递载体
MVC模式(一种设计模式):
model、view、controller
视图view、控制器controller用于Web;模型model用于service、dao
异步调用(目前):
#{}:用于绑定参数值到SQL语句中的占位符;动态值:比如说age=?,?具体根据前端输入
${}:用于绑定常量值到SQL语句中的占位符;具体的值:比如说age=3
单例模式
工厂模式
代理模式
模板方法模式
是一种通过使用依赖注入(DI)实现方式,用来解决Java组件间的耦合问题。
依赖注入(DI):通过类外部注入依赖对象,来解决类与类之间的依赖关系。类本身不创建依赖对象,由外部容器负责创建并注入依赖对象。
面向切面编程。对多个对象产生影响的共同行为和逻辑,抽取并封装成一个可重用的模块。
权限管理、表单验证、事务管理、信息过滤、拦截器、过滤器、页面转发等
用于构建Web应用程序的一种MVC架构
(1)前端控制器:接受请求、响应结果;是整个流程的控制中心,由它调用其他组件处理用户请求;降低组件之间的耦合性。
(2)处理器映射器(…Mapping):根据请求url和方法(get、post)查找处理器
(3)处理器适配器:通过适配器执行处理器
(4)处理器:对具体用户请求进行处理
(5)视图解析器:根据逻辑视图名解析为具体的视图
(6)视图:使用模型数据渲染视图,生成html
Spring Boot是一个基于Spring框架的快速开发工具,用于简化Java应用程序的开发和部署。它采用约定大于配置的理念,提供了一套默认的配置,让开发者能够更加专注于业务逻辑的实现而不用过多关注配置。
微服务架构的一种实现框架
是用于构建分布式系统和微服务架构的一套开源框架。基于Spring Boot,提供丰富的
组件。(多个组件的集合)
优点:
1.模块化和松耦合
2.独立开发和部署:每个微服务都可独立开发和部署
3.容错性:一个服务出现故障不影响其他服务运行
4.可扩展性:可根据需求独立水平扩展
核心组件:
1.Eureka服务注册与发现:微服务之间的注册与发现(服务注册、服务提供)
2.Feign服务调用:用于简化微服务之间的调用(使代码更加的简洁/自动根据参数拼接http请求/)
3.Ribbon负载均衡:用于多个服务实例之间进行负载均衡,提高系统可用性和性能
4.Config Server配置中心:使各个微服务配置进行集中管理,本质上也是一个微服务
5.Hystrix断路器:防止服务调用失败导致级联故障,提供服务熔断和线程隔离
6.Gateway、Zuul网关:作为API网关,可以简化微服务架构中的请求路由和过滤处理
Message Queue 消息队列,分布式系统的通信方式之一
优势:
应用解耦:提高系统容错性、可维护性
异步提速:提升用户体验和系统吞吐量
削峰填谷:提高系统稳定性
劣势:
系统可用性降低:MQ宕机
系统复杂度提高:消息重复消费、丢失、传递顺序
一致性问题:部分系统处理失败
1. 基于AMQP协议使用Elang语言开发
2. 提供6种工作模式
3. AMQP是协议,JMS是API规范接口
4. 工作模式:
1、2种只有一个消息队列,一个消息只能被一个消费者接收
被多个消费者接收
发布与订阅模式:
5. 生产者到MQ,控制消息投递可靠性
1. Confirm确认模式:producer到exchange回返回一个confirmCallback(无论消息是否成功到达exchange)
2. Return退回模式:exchange到queue失败则返回一个returnCallback
6.MQ到消费者,消费端收到消息后确认方式
自动确认:收到消息则回复,不管消息处理是否异常
手动确认
7.死信队列(交换机)
是服务器,是一个分布式全文搜索引擎(yin qing),能处理PB级别的数据
全文搜索:处理大量文本数据
强大的查询语言:提供丰富的查询语言,支持复杂查询和过滤操作,
分布式架构:elasticSearch是一个分布式系统
多语言支持:java、python、js
1. 线性结构的存储结构
顺序存储->顺序表
链式存储->链表
1. 顺序查找
顺序查找适用于存储结构为数组或链表(顺序存储、链式存储)
- public static int sequenceSearch(int[] arr, int k){
- for (int i = 0; i < arr.length; i++){
- if (k == arr[i]){
- return i;
- }
- }
- return -1;
- }
2. 二分查找(折半查找)
元素必须有序,且是顺序表
- public static int binSearch(int[] arr, int num){
- int mid = 0;
- int min = 0;
- int max = arr.length-1;
- while (min <= max){
- mid = (min + max)/2;
- if (arr[mid] < num){
- min = mid +1;
- }else if (arr[mid] > num){
- max = mid -1;
- }else {
- return mid;
- }
- }
- return -1;
- }

3. 插值查找
有序查找;适合表长较大,关键字分布均匀的查找表
基于二分查找的思想:mid = (low + hight)/2 = low + 1/2 * (hight – low)
mid = low + (key – arr[low])/(arr[hight] – arr[low]) * (hight – low)
把1/2改成自适应(关键字所处的位置):(key – arr[low])/(arr[hight] – arr[low])
算法:和二分查找一样,除了mid计算改为
mid = low + (key – arr[low])/(arr[hight] – arr[low]) * (hight – low)
稳定算法:冒泡、插入、归并
1. 冒泡排序(交换)
- //n-1趟
- for (int i = 1; i < arr.length; i++){
- for (int j = 0; j < arr.length - i; j++){
- if (arr[j] > arr[j+1]){
- temp = arr[j];
- arr[j] = arr[j+1];
- arr[j+1] = temp;
- }
- }
- }
2. 选择排除(从后面选最小,与前面的交换)
每次记录最小的min及其位置
从待排序中选择最小的放到已排序的末尾
- // 进行 n-1 趟
- for (int i = 0; i < arr.length-1; i++) {
- int k = i; //记录一趟最小值的位置
- int min = arr[i];
- for (int j = i+1; j < arr.length; j++) {
- if (arr[j] < min) {
- min = arr[j];
- k = j;
- }
- }
- if (k != i) { //说明更新了最小值
- temp = arr[i];
- arr[i] = min;
- arr[k] = temp;
- }
- }

3. 直接插入排序(比较前面)(移动)
从待排序中依次选择元素插入到已排序的合适位置
比较,移动元素,最后再插入
- int current, preIndex;
- for (int i= 1; i< arr.length; i++){
- current = arr[i]; //每一趟待排序的元素
- preIndex = i -1; //待排序的前一个地址
- while(preIndex >= 0 && current < arr[preIndex]){
- //跟已排序的比较,直到首位
- arr[preIndex +1] = arr[preIndex];
- preIndex--;
- }
- arr[preIndex +1] = current; //合适位置
- }
- return arr;
4. 希尔排序
插入排序的改进版,把插入排序的间隔1改为gap
直接插入排序的改进版;分为(若干)m组,每个相隔m;每组分别进行插入排序
第一趟:m1=n/2
第二趟:m2=n/2^2
- public static int[] ShellSort(int[] arr){
- int len = arr.length;
- int gap = len / 2;
- int current, preIndex;
- while (gap > 0){
- for (int i = gap; i < len; i++){
- current = arr[i];
- preIndex = i - gap;
- while(preIndex >= 0 && current < arr[preIndex]){
- arr[preIndex + gap] = arr[preIndex];
- preIndex -= gap;
- }
- arr[preIndex + gap] = current;
- }
- gap /= 2;
- }
- return arr;
- }

5. 归并排序
- //归并排序
- /**
- * 递归分治+排序
- * @param arr
- * @param left
- * @param right
- * @param temp
- * @return
- */
- public static int[] mergeSort(int[] arr, int left, int right, int[] temp){
- if (left < right){ //分治到一个元素时退出递归
- int mid = (left + right)/2;
- mergeSort(arr, left, mid, temp);
- mergeSort(arr, mid+1, right, temp);
- merge(arr, left, mid, right, temp);
- }
- return arr;
- }
- /**
- * 排序
- * @param arr
- * @param left
- * @param right
- * @param temp
- * @return
- */
- public static int[] merge(int[] arr, int left, int mid, int right, int[] temp){
- int i = left; //左子组的首个索引
- int j = mid+1; //右子组的首个索引
- int k = 0; //临时数组首个索引
-
-
- while (i <= mid && j <= right){ //左或右子组一方完成排序则退出循环
- if (arr[i] <= arr[j]){
- temp[k++] = arr[i++];
- }else {
- temp[k++] = arr[j++];
- }
- }
- //把剩余的子组依次放到临时数组
- while (i <= mid){
- temp[k++] = arr[i++];
- }
- //把剩余的子组依次放到临时数组
- while (j <= right){
- temp[k++] = arr[j++];
- }
- //复制到原来数组
- int tempLeft = left;
- int t = 0;
- while (tempLeft <= right){
- arr[tempLeft++] = temp[t++];
- }
- return arr;
- }

6. 堆排序
- // 堆排序
- /**
- *
- * @param arr
- * @return
- */
- public static int[] HeapSort(int[] arr){
- int len = arr.length;
- // 构建大顶堆
- BuildMaxHeap(arr, len);
- while (len > 1){
- // 对堆顶与堆尾交换
- int temp = arr[0];
- arr[0] = arr[len-1];
- arr[len-1] = temp;
- // 将有序的减掉
- len--;
- // 调整
- AdjustHeap(arr, len, 0);
- }
- return arr;
- }
-
- /**
- * 构建大顶堆
- * @param arr
- * @param len
- */
- public static void BuildMaxHeap(int[] arr, int len){
- // 从最后一个非叶子结点开始直到堆顶(从左至右,从下至上)
- for (int i = (len-2)/2; i >= 0; i--){
- AdjustHeap(arr, len, i);
- }
- }
-
- /**
- * 调整堆
- * @param arr
- * @param len
- * @param i
- */
- public static void AdjustHeap(int[] arr, int len, int i){
- int maxIndex = i;
- //父与左子比较
- if (2*i + 1 < len && arr[2*i + 1] > arr[maxIndex]){
- maxIndex = 2*i + 1;
- }
- //父与右子比较
- if (2*i + 2 < len && arr[2*i + 2] > arr[maxIndex]){
- maxIndex = 2*i + 2;
- }
- // “最大值”位置有变
- if (i != maxIndex){
- int temp = arr[i];
- arr[i] = arr[maxIndex];
- arr[maxIndex] = temp;
- // 递归调整子树
- AdjustHeap(arr, len , maxIndex);
- }
- }

7. 快速排序(递归)
随机选择一个基准元素,每一趟都将数据划分为两部分,一部分小于基准元素,另一部分则大于基准,再递归对两部分元素排序
- public static void test4(int[] arr, int start, int end){
- if (start >= end) return;
- int left = start, right = end, k = arr[start];
- while(left < right){
- //取左为基准,先比较右边,反之同理
- while (left < right && arr[right] > k) right--;
- arr[left] = arr[right];
- while (left < right && arr[left] <= k) left++;
- arr[right] = arr[left];
- }
- arr[right] = k; //此时left == right
- test4(arr, start, right-1);
- test4(arr, right+1, end);
- }
1. 解决哈希冲突
1.开放定址法:当遇到冲突时,新的键值会插入到哈希表的下一个可用槽
可用槽:
1.线性探测法:( v+i ) % leng
2.平方探测法(二次探测法):( v +/- i^2 )% leng
2. 树的层次遍历
父先出队,再将子入队
1. TCP/IP四层协议(合并了后三层和前两层)
链路层、网络层、传输层、应用层
把OSI后三层合并了
2. https连接过程
1.客户端发送支持的加密协议以及版本(Hello)
2.服务端从中筛选合适的加密协议
3.服务端返回证书,证书中有公钥(Hello)
4.客户端使用根证书验证证书合法性
5.客户端生成对称密钥,通过证书中的公钥加密,发送到服务器端
6.服务端使用私钥解密,获取对称密钥,使用对称密钥加密数据
7.客户端解密数据,SSL(通讯安全加密协议)开始通讯
3. IP/TCP
IP:不可靠,无连接
UDP:不可靠,无连接
TCP:可靠,面向连接
4. IP地址分为5类
A类地址:以0开头,范围从0.0.0.0到127.255.255.255。
B类地址:以10开头,范围从128.0.0.0到191.255.255.255。
C类地址:以110开头,范围从192.0.0.0到223.255.255.255。
D类地址:以1110开头,范围从224.0.0.0到239.255.255.255,用于多播(Multicast)通信。
E类地址:以1111开头,范围从240.0.0.0到255.255.255.255,保留未分配的地址。
5. CRC(循环冗余校验)
若信息码字为111000110;生成多项式为X5+X3+X+1(x^5+x^3+x+1)。计算CRC
校验码
生成多项式系数作为除数(101011),最高幂次数(5)作为校验码位数,将信息码
后补5个0(11100011000000)以“模2除法”(异或)除以系数(101011),余数(11001)即为检验码
6. http请求
由请求行+请求头+请求体组成
1. 请求行:请求方式+URL+协议版本
2. 请求头:host,定义请求体格式、长度等
3. 请求体:向服务器提交的数据
get | post |
向服务器获取数据 | 向服务器提交数据 |
数据放在URL地址之后 | 数据放在请求体(request body)中 |
不安全,不适合传递敏感信息 | 安全,适合传递敏感信息 |
Get请求可被缓存 | post请求不可缓存 |
产生一个tcp数据包 | 产生两个tcp数据包 |
ls: 列出当前目录下的文件和子目录
cd: 切换当前目录
pwd: 显示当前工作目录的绝对路径
mkdir: 创建新目录
rm: 删除文件或目录
cp: 复制文件或目录
mv: 移动或重命名文件或目录
cat: 查看文件内容
grep: 在文件中搜索指定的模式
find: 在文件系统中查找文件
chmod: 修改文件或目录的权限
chown: 修改文件或目录的所有者
sort:对文件进行排序
gzip:压缩文件
ps: 显示当前运行的进程
kill: 终止正在运行的进程
ping: 测试与另一个主机的连接状态
ifconfig: 显示网络接口的配置信息
netstat: 显示网络连接和路由表
tar: 压缩和解压缩文件
1. SSM:Sping、SpingMVC、MyBatis框架的整合
2. Spring Security
是一个安全框架,用于Spring应用程序中提供身份认证、授权和其他安全功能。它基于Spring框架,可以与Spring框架无缝集成。
身份认证:提供多种身份认证方式,基于表单、HTTP基本认证、LDAP、OAuth等,通过认证,用户可以登录系统并获取访问权限
授权:基于用户的角色和权限,对用户进行访问控制
防止常见安全威胁:
跨站脚本攻击(XSS):允许攻击者向网页注入恶意脚本
跨站请求伪造(CSRF):诱导用户点击链接或访问特制网站
SQL注入:在应用程序的输入中注入恶意SQL查询来访问或篡改数据库的数据
点击劫持
Session管理
Remenber Me功能:用户可选择记住登录状态,下次访问自动登录
CSRF防护:
自定义过滤器
3. Jwt(Json Web Token)
是一种用于认证和授权的开放标准;由三部分组成的字符串,头部(Header)、载荷(Payload)、签名(Signature)
4. Spring
轻量级开源框架,提供给容量管理,依赖注入(IOC)了和面向切面编程(AOP),用于简化java应用的开发
IOC:控制反转,是一种依赖注入,解决java应用程序中组件之间的耦合问题
AOP:面向切面编程,解决java应用程序中横切关注点的问题
5. SpringMVC
基于Spring框架的Web应用开发框架
简化配置:简化maven配置,parent这种方式,一站式引入各种依赖
基于注解的零配置思想
和各种流行框架无缝整合
6. SpringBoot
用于快速开发Spring应用程序的开源框架
打包成jar文件,内嵌tomcat和jetty容器,不需要单独安装容器
简化maven配置,parent这种方式,一站式引入需要的各种依赖
基于注解的零配置思想
和各种流行框架,spring mvc,mybatis,spring cloud无缝整合
7. Maven
项目管理工具
(1)项目构建:提供标准的、跨平台的自动化项目构建方式(源代码放在src/main/java目录)
(2)依赖管理:方便快捷的管理项目依赖资源(jar包),避免资源间版本冲突问题,
使用pom.xml管理项目。
(统一开发结构:提供标准的、统一的项目结构)
8. InnoDB
MySQL存储引擎之一(默认的存储引擎),支持事务、行级锁、外键约束,适用于大型数据库。
事务隔离级别:读已提交;读未提交;可重复读;串行化
9. RabbitMq
消息队列,
10. Html/html5
用于创建网页结构和内容的标记语言;定义网络各种元素,标题、段落、链接、图像
Html5是html的第五版本,引入新的语义化标签和多媒体功能
11. 前端
HTML :用于定义网页的结构和内容
Css/css3:用于控制网页的样式和布局,如:颜色、字体、大小、位置
Css3是css的第三版本,引入许多新的特性:渐变、阴影、动画
javaScrip:实现网页的交互和动态效果(脚本语言)
Vue、React框架
Redis: 6379
MySQL: 3306
HTTP:80
HTTPS: 443
SSH: 22
MongoDB: 27017
2. Autowired和Resource的区别
都是用于依赖注入的注解
@Autowired: 这个是Spring框架的注解,用于自动装配Bean的依赖关系 ;通过类型
进行依赖注入,默认按照类型进行依赖匹配
@Resource是java标准的注解,由JavaEE提供;按照名称进行依赖注入,通过指定
名称查找对应的Bean进行注入
3. Java有哪些集合类
ArrayList、LinkedList、Stack、HashSet、TreeSet、HashMap、TreeMap
HashMap:基于哈希表实现;提供高效快速插、删、查操作;无序(由于键值对无序)、
时间复杂度o(n)、哈希冲突;
TreeMap:基于红黑树实现;有序、时间复杂度O(log n)、性能稳定
4. 读锁和读写锁的区别
多线程下读写操作并发控制机制
写锁:是一种独占锁,当一个线程获取写锁时,其他线程无法获取读锁或写锁
5. 进程和线程的区别
进程是操作系统中资源分配的基本单位,拥有独立的内存空间和系统资源,进程间通信
要通过IPC机制
线程是进程中的一个执行单元,共享所属进程的所有内存空间和系统资源,线程间通信
可以直接读写共享内存
一句话:进程是资源分配的单位,线程是执行的单位
6. 进程间的通信方式
管道、消息队列、共享内存、信号量、套接字、文件
7. 三次握手、四次挥手
当客户端向服务端发送数据时,需要先建立TCP连接,这个过程叫做“三次握手”,
TCP连接的释放需要“四次挥手”
三次握手:
客户端向服务端发送SYN报文,表示客户端请求建立连接
服务端收到后,向客户端发送SYN+ACK报文,表示服务端已收到请求并同意
客户端收到后,向服务端发送ACK报文,表示客户端已收到服务端的确认,
连接建立完成
四次挥手:
(客户端和服务端各发一次断开请求并发送确认收到)
客户端发送FIN报文,表示客户端不再发送数据,请求断开连接
服务端收到后,向客户端发送ACK报文,表示已收到请求并准备好断开连接
服务端发送FIN报文,表示服务端不再发送数据,请求断开连接
客户端收到FIN报文,向服务端发送ACK报文,表示已收到服务端的请求并
断开连接
8. Full GC
全局垃圾回收,指垃圾收集器在回收垃圾时,对堆内存中所有的对象进行全面的清理和回收。
9. Collection接口中List、Set、Map的区别
都是Collection接口的子接口
List:有序集合、允许重复元素;常用实现类:ArrayList、LinkedList、Vector
Set:不允许重复元素;常用实现类:HashSet、LinkedHashSet、TreeSet
Map:键值对存储;常用实现类:HashMap、LinkedHashMap、TreeMap
10. get和post的区别
get | post |
向服务器获取数据 | 向服务器提交数据 |
通过URL来传递数据 | 把参数放在request body中 |
不安全,不适合传递敏感信息 | 安全,适合传递敏感信息 |
可被缓存 | 不可缓存 |
产生一个tcp数据包 | 产生两个tcp数据包 |
11. http和https的区别
客户端和服务器之间传输数据的协议
http:用于在网络上传输超文本的协议;数据传输过程是明文的(不加密的),可能被
拦截、窃听;不提供数据完整性校验,传输过程可能会被篡改
https:是http的安全版本,使用SSL或TLS协议对数据进行加密和认证;提供数据完整性校验,一旦篡改,接收方会发现不匹配的签名
12. 负载均衡(nginx)
场景:当一个网站或应用程序要处理大量的并发请求时
处理:将请求分发到多台服务器上,以均匀分摊流量和请求负载
作用:提高系统的性能、可用性、可扩展性
13. 异常
检查型异常:
NullPointerException
ClassCastException
FileNotFoundException
运行时异常:(不用编程时声明)
IndexOutOfBoundsException
14. 数据库视图的作用
15. Spring Cloud、RabbitMq的基本概念
16. XX银行面试
浏览器(session、storage)
http、tcp、udp
状态码(1-5)
滑动窗口(连接、传输数据)
拥塞控制、流量控制
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。