Java基础
String StringBuffer StringBuilder
String是不可变长的
StringBuffer和StingBuilder是可变长的,StringBuilder性能更高,但是线程不安全,StringBuffer是线程安全的
JVM组成部分
类加载器,运行时数据区,执行引擎,本地库接口
首先通过类加载器将Java代码转化为字节码文件,运行时数据去将字节码文件加载到内存中,字节码是JVM的i一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解析器执行引擎,将字节码文件翻译成底层系统指令,再交给cpu执行,这个过程还要吊用其他语言的本地接口来实现整个程序功能
运行时数据区
程序计数器:当前进程所执行的字节码行号指示器,字节码解析器的工作是通过改变程序计数器的,来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程等基础功能都需要程序计数器来完成
虚拟机栈:用于存储局部变量表、操作数栈、动态链接、方法出口等信息
本地方法栈:与虚拟机栈作用一样,但是本地方法栈是为虚拟机调用Native方法服务,而虚拟机栈是为java方法服务的。
堆:java虚拟中最大的一块,几乎所有的对象实例都在这里分配内存,被线程共享
方法区:用于存储已被虚拟机加载的类信息、常量、静态敞亮、及时编译后的代码等数据
ArraryList 和 Vector区别
Vector有synchronized保证线程安全
HashMap
1.8后 数组+链表+红黑树(链表长度超过八之后改红黑树)
线程不安全 并发环境最好不要使用ConcurrentHashMap代替
预估大小 避免频繁扩容 消耗内存
size一定为2的n次幂 这样可以使产生的hashCode值与运算后产生的index值分布更加均匀(2的n次幂&hash 全一与运算 减少了很多hash碰撞)
put
1.对key的hashCode()做hash运算,计算index;
2.如果没碰撞直接放到bucket⾥;
3.如果碰撞了,以链表的形式存在buckets后;
4.如果碰撞导致链表过⻓(⼤于等于TREEIFY_THRESHOLD),就把链表转换成红⿊树(JDK1.8中的改动);
5.如果节点已经存在就替换old value(保证key的唯⼀性)
6.如果bucket满了(超过load factor*current capacity),就要resize
get
1.对key的hashCode()做hash运算,计算index;
2.如果在bucket⾥的第⼀个节点⾥直接命中,则直接返回
3.如果有冲突,则通过key.equals(k)去查找对应的Entry
4.若为树,则在树中通过key.equals(k)查找O(logn);
5.若为链表,则在链表中通过key.equals(k)查找,O(n)。
HashMap,HashTable,ConcurrentHashMap
HashMap key和value都可以为null
HashTable key和value都不可以为null
ConcurrernHsahMap 添加了synchronized锁
sleep()和wait()
每个对象都有其对应的等待池 和 锁池
对象等待池中的线程不会抢占该锁对象 对象锁池中的线程会抢占该锁对象
sleep()被调用 线程不会释放锁对象
wait()方法被调用线程会释放锁对象,进入等待池,直到其他线程调用notify()/notifyAll()方法, notify()/notifyAll()方法会从等待池中唤醒一个/全部的线程 加入到对象的锁池 ,线程重新去抢占锁对象
一般来说 不会在wait方法中加等待时间
notify()和notifyAll()
唤醒一个/唤醒全部线程
Integer int 比较 自动拆箱
- Integer与int比较 Interger会自动拆箱转化int 所以此时只要值相等 就为true
- Integer与Integer比较 只要一方存在new出的对象 比较的就是引用 如果都是直接复制,存在 127缓存
@Test
public void method(){
Integer a = new Integer(127);
Integer a1 = new Integer(127);
Integer a2 = 127;
Integer a4 = 127;
int a3 = 127;
System.out.println(a==a1);//false
System.out.println(a==a2);//false
System.out.println(a3==a2);//true
System.out.println(a==a3);//true
System.out.println(a2==a4);//true
System.out.println("==========================================");
Integer b = new Integer(128);
Integer b1 = new Integer(128);
Integer b2 = 128;
Integer b4 = 128;
int b3 = 128;
System.out.println(b==b1);//false
System.out.println(b==b2);//false
System.out.println(b3==b2);//true
System.out.println(b==b3);//true
System.out.println(b2==b4);//false
}
byte short运算
防止溢出自动向上转
byte+byte=int
byte+short=int
byte+int =int
short+short=int
long+(整形)=long
double+(浮点)=double
float+float=float
int+float=float
Java类的加载顺序
父类静态变量,父类静态代码块,子类静态变量,子类静态代码块,父类非静态变量,父类非静态代码块,父类构造函数,子类非静态变量,子类非静态代码块,子类构造函数
构造函数:在创建对象是掉用 不同参数掉用不同的构造函数
构造代码块:在所有构造函数前掉用,依托于构造函数
静态代码块:类加载时被掉用
多线程
创建线程的几种方式
创建线程池的七个参数
- corePoolSize
表示当前线程池的核心线程数大小,即最小线程数(初始化线程数),线程池会维护当前数据的线程在线程池中,即使这些线程一直处于闲置状态,也不会被销毁;
- maximumPoolSize
表示线程池中允许的最大线程数;后文中会详细讲解
- keepAliveTime
表示空闲线程的存活时间,当线程池中的线程数量大于核心线程数且线程处于空闲状态,那么在指定时间后,这个空闲线程将会被销毁,从而逐渐恢复到稳定的核心线程数数量;
- unit
当前unit表示的是keepAliveTime存活时间的计量单位,通常使用TimeUnit.SECONDS秒级;
- workQueue
任务工作队列;后文会结合maximumPoolSize块来讲
- threadFactory
线程工厂,用于创建新线程以及为线程起名字等
- handler
拒绝策略,即当任务过多无法及时处理时所需采取的策略;
数据库
缓存穿透、击穿、雪崩
缓存穿透:请求非法数据:缓存中没有数据 数据区也没有数据
解决方法:前后端校验 空值缓存(时间较短) 哈希校验
布龙过滤器 :通过多个hash函数 计算hash值判断记录01 判断是否存在(全标识存在)
缓存击穿:大量请求(同一个key) 同时请求数据库
解决方法:保证当缓存失效时候 不让大量请求访问到数据库 分布式锁 只放一个请求进去 热点数据不过去 二级缓存
缓存雪崩:缓存失效(不同的key) 大量请求到数据库
解决方法:缓存时间随机(避免不同缓存同时失效) 上锁
MyISAM和InnoDB区别
MyISAM不支持行级锁、事务、多版本并发控制MVVC、外键,InnoDb支持
InnoDB:聚集索引,使用 B+ 树作为索引结构,数据文件和索引绑在一起,必须要有主键。
MyISAM:非聚集索引,使用 B+ 树作为索引结构,索引和数据文件是分离的。
Mysql索引
聚集索引:InnoDB存储引擎的表会存在主键(唯一非null),如果建表的时候没有指定主键,则会使用第一非空的唯一索引作为聚集索引,否则InnoDB会自动帮你创建一个不可见的、长度为6字节的row_id用来作为聚集索引。
单列索引:单列索引即一个索引只包含单个列
组合索引:组合索引指在表的多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用。使用组合索引时遵循最左前缀集合
唯一索引:索引列的值必须唯一,但允许有空值。若是组合索引,则列值的组合必须唯一。主键索引是一种特殊的唯一索引,不允许有空值
普通索引:是MySQL中的基本索引类型,允许在定义索引的列中插入重复值和空值
全文索引:全文索引类型为FULLTEXT,在定义索引的列上支持值的全文查找,允许在这些索引列中插入重复值和空值。全文索引可以在CHAR、VARCHAR或者TEXT类型的列上创建
空间索引:空间索引是对空间数据类型的字段建立的索引,MySQL中的空间数据类型有4种,分别是GEOMETRY、POINT、LINESTRING和POLYGON。MySQL使用SPATIAL关键字进行扩展,使得能够用于创建正规索引类似的语法创建空间索引。创建空间索引的列必须声明为NOT NULL
最左前缀原则:在使用组合索引时候,查询条件要从组合索引最左匹配,如果没有则不是使用索引,顺序无所谓,mysql执行时会优化;
回表:查询语句通过普通索引查到的数据只存放了PK,还要再次回表通过PK查询整个数据,可以通过使用聚集索引,或者联合索引触发索引覆盖解决回表问题
Spring
SpingMVC流程及组件
- 用户发送请求至前端控制器DispatcherServlet;
- DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;
- 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生 成)一并返回给DispatcherServlet;
- DispatcherServlet 调用 HandlerAdapter处理器适配器;
- HandlerAdapter 经过适配调用 具体处理器(Handler,也叫后端控制器);
- Handler执行完成返回ModelAndView;
- HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
- DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
- ViewResolver解析后返回具体View;
- DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中
- DispatcherServlet响应用户。
组件说明
- 前端控制器 DispatcherServlet(不需要程序员开发)
作用:接收请求、响应结果,相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。
- 处理器映射器HandlerMapping(不需要程序员开发)
作用:根据请求的URL来查找Handler
- 处理器适配器HandlerAdapter
注意:在编写Handler的时候要按照HandlerAdapter要求的规则去编写,这样适配器
HandlerAdapter才可以正确的去执行Handler。 - 处理器Handler(需要程序员开发)
- 视图解析器 ViewResolver(不需要程序员开发)
作用:进行视图的解析,根据视图逻辑名解析成真正的视图(view)
- 视图View(需要程序员开发jsp)
View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等等)
网络
TCP/UDP
TCP:提供面向连接的服务,在传送数据之前必须先建立连接,数据传送完成后要释放连接。因此TCP是一种可靠的的运输服务,但是正因为这样,不可避免的增加了许多的开销,比如确认,流量控制等。对应的应用层的协议主要有 SMTP,TELNET,HTTP,FTP 等。(因为tcp的超时重传功能,所以在客户端发送数据之后,如果收不到服务端的响应,就会再次发送数据)
UDP:不面向连接,在传送数据前不需要先建立连接,远地的主机在收到UDP报文后也不需要给出任何确认。虽然UDP不提供可靠交付,但是正是因为这样,省去和很多的开销,使得它的速度比较快,比如一些对实时性要求较高的服务,就常常使用的是UDP。对应的应用层的协议主要有 DNS,TFTP,DHCP,SNMP,NFS 等。
其他
@Autowired和@Resource
@Autowired 按照type注入
@Resource 按照name type注入
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
propagation = Propagation.REQUIRED
此方法如果运行在已存在的事务中 就不会另起事务 异常后和存在的事务一起回滚,反之则启动一个新的事务
rollbackFor=Exception.class
如果类加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。默认为运行时异常才会回滚