进程和线程的理解
进程是系统资源分配和调度的基本单位,进程切换开销大,线程是cpu分配和调度的基本单位,线程开销小,一个进程可以有多个线程
线程的生命周期,线程有几种状态
创建new:新建的线程
就绪runnable:调用start()方法后,等待cpu,谁抢占到cpu谁运行
运行running:获得了cpu后,开始执行
阻塞blocked:在运行态因为某种原因暂时停止运行,直到变为就绪态
销毁dead:执行结束或出现异常或被强制终止
线程间通信方式
volitale内存可见性
synchronized:wait()等待,notify()唤醒,notifyall()唤醒全部
lock:await()等待,signal()唤醒,signalall()唤醒全部
阻塞队列 :put()放入队尾,队满则阻塞,take()取出队头,队空则阻塞
所有结点的左右子树高度差不超过1,左子树小于父结点,右子树大于父结点,实现快速查找,因为二叉查找树有些情况会变成链表,时间复杂度为O(n),平衡二叉树时间复杂度为O(lgn)
红黑树比平衡二叉树好在哪里
红黑树查找效率比较低,但是插入删除效率比较高
在什么场景会用到红黑树,为什么它们会用红黑树
TreeMap,TreeSet,可以实现自然排序和定制排序
list
有索引
arraylist
通过数组实现
查找效率高,支持随机访问,添加删除效率低,需要移动元素,超过数组容量需要复制所有元素到新的更大的数组
linkedlist
通过链表实现
查找效率低,不支持随机访问,添加删除效率高,不需要移动元素,可以一直添加
map
存储键和值,将键映射到值,键不能重复,一个键最多对应一个值
hashmap
通过哈希表实现
哈希表通过数组和链表实现
输入输出顺序不一致
linkedhashmap
通过哈希表和链表实现
输入输出顺序一致
treemap
通过红黑树实现
hashtable
和hashmap一样,方法用synchronized修饰,多了线程安全,操作时候会将整个hashtable锁住,其他线程无法操作
concurrent hashmap
和hashtable一样,value和哈希表用volatile修饰,只锁数组的一个位置,不影响其他位置
set
和map一样,只是把value设置成了null,只使用key
volatile和synchronized的区别
volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
二叉查找树
左根右,从小到大
时间复杂度O(lgn)
b树
二叉查找树深度太大,磁盘IO次数过多,为了减少磁盘IO的次数,瘦高变成矮胖
节点中元素从小到大排列,中间空着的划分子节点
b+树
相比b树,中间结点只有索引没有数据,更加矮胖
指针指向第一个叶子结点,形成链表,便于查询
红黑树
特点
1结点颜色为红色或者黑色,叶子结点为黑色,根节点为黑色
2如果一个节点是红色,那么它的子节点必须是黑色
3从一个节点到它的子孙节点必须包含相同数量的黑色节点
时间复杂度
O(lgn)
用途
解决了二叉查找树的线性问题,接近于平衡二叉查找树
存储有序的数据,如TreeMap,TreeSet
内存模型
本地方法栈:c++的native方法
程序计数器:程序当前运行的位置
栈:函数当前运行过程中的临时变量(引用类型,即地址,指向堆)
以上三个是线程私有
方法区:静态方法或变量,类加载器
堆:对象
gc(垃圾回收)
可达性分析
gcroot不能删除的
和gcroot没有引用链相连的对象:栈,本地方法栈,方法区中引用的对象
gc方法
标记清理:先标记再清理,内存碎片
标记整理:先标记再清理,清理之后移动到空位,代价太大
复制:内存分为1区和2区,先用1区,把没有标记的复制到2区,清理1区,需要2倍内存
实际gc
young区 1:1:8
survive0
survive1
eden:新创建的对象,快满了之后用复制算法复制到survive区,两个survive区交替使用
old区
年龄>6的对象:每次gc年龄+1,满6次复制到old区
大对象
old区满了之后进行fullgc,java程序暂停,进行标记清理或者标记整理
什么是线程
是进程中的单个顺序控制流,是一条执行路径
一个程序只有一条执行路径就是单线程程序,一个程序有多条执行路径就是多线程程序
创建线程
继承thread类
实现runnable方法
线程池
线程池优点:
降低创建和销毁线程的消耗,提高线程利用率
任务来了,如果有空闲线程可以直接运行,提高响应速度
线程池可以统一管理线程,提高线程的可管理性
创建线程池
newCachedThreadPool() 可缓存
newFixedThreadPool() 可指定大小
newScheduledThreadPool() 可以控制时间和周期
newSingleThreadPool() 单个线程
线程池参数
corePoolSize核心线程池大小:最小线程数量,即使空闲也不会被销毁
maximumPoolSize线程池最大线程数量:任务被提交到线程池以后,首先会找有没有空闲线程,如果没有则缓存到工作队列,工作队列满了则创建新新线程,不能超过线程最大数量,把队头任务交给新线程,把这个任务放到队尾
keepAliveTime空闲线程存活时间:线程空闲,且数量大于corePoolSize,则指定时间后被销毁
unit:keepAliveTime的计量单位
workQueue工作队列:新任务被提交时,如果没有空闲线程,先进入工作队列队尾
锁/同步
synchronize关键字
发生异常自动解锁,不会发生死锁,
不能响应中断
竞争不激烈性能好
lock接口
发生异常不会自动解锁,需要手动解锁
可以用interrupt来响应中断
竞争激烈性能好
常用排序算法
1.冒泡排序
相邻的两个比较,把最大的放在后面,n趟排序可以把第n大的放在后面。
2.选择排序
选择最大的,和最后一个交换,剩余部分重复这个过程。
3.插入排序
分为已经有序部分和无序部分,从无序部分取一个数,从大到小比较,若有序的数大于取的数,有序的数往后移动,直到有序的数不大于取的数,可以确定位置。
4.快速排序
随机选一个数作为中心轴,左边都比它小,右边都比它大,在每个区间递归进行这个步骤。
5.堆排序
项目用了哪些框架,每个框架是什么意思,用来干什么
spring:控制反转ioc,面向切面aop
springMVC:model数据承载和业务处理,view视图,controller控制器
mybatis:建立和数据库的映射
shiro:身份验证和权限管理
面向对象
面向过程更注重处理问题的步骤和顺序,面向对象更注重处理问题有哪些参与者、各自需要做什么。
面向过程比较直接高效,面向对象更易于复用、扩展和维护。
特性:封装、继承、多态。
封装:明确标识出允许外部使用的成员函数和数据项,内部细节对外部调用透明。
继承:子类共性的属性和方法直接使用父类的,再添加自己独有的。
多态:接口有不同的实现类。
JDK、JRE、JVM的区别和联系
JDK:java development kit java开发工具,提供给开发人员使用。
JRE:java runtime environment java运行时环境,提供给运行java程序的用户使用。
JVM:java virtual machine java虚拟机。
JDK包含JRE,JRE包含JVM。
.java文件经过javac编译成.class文件,.class文件可以到处运行,放到windows或者linux版本的jvm上,jvm调用lib里面的类库去解释.class文件,将.class文件翻译成机器码,映射到操作系统,然后调用。
重载和重写的区别
重载:发生在同一个类中,方法名相同,参数列表不同。
重写:发生在父子类中,方法名和参数列表相同,方法体不同,如果父类方法修饰符为private那么子类不能重写这个方法。
接口和抽象类
抽象类中可以有普通成员方法,接口中的方法必须全部是抽象方法。
抽象类只能继承一个,接口可以实现多个。
抽象类中的成员变量可以是各种类型的,接口中的成员变量只能是public static final类型的
权限修饰符
同一个类中 同一个包中 不同包的子类 不同包的无关类
private yes
默认 yes yes
protect yes yes yes
public yes yes yes yes
final
最终的。
修饰类:表示类不可以被继承。
修饰方法:表示方法不可以重写。
修饰变量:表示变量一旦被赋值就不可以修改它的值。
static
被类的所有成员共享
可以使用类名和对象名调用,推荐使用类名调用
static修饰的方法只能调用static修饰的方法,没有被static修饰的方法可以调用任意方法
String、StringBuffer、StringBuilder
String是final修饰的,不可变,每次修改会产生新的String对象。
StringBuffer和StringBuilder都是在原来的对象上操作的,底层是数组,可以用append()方法增添新元素,性能StringBuilder>StringBuffer>String。
StringBuffer是线程安全的,StringBuilder是线程不安全的,StringBuffer的方法都是synchronized修饰的。
修改少时使用String,经常需要修改时使用StringBuffer和StringBuilder,多线程共享变量时使用StringBuffer。
List和Set的区别
List存储有序、可重复的元素,支持下标访问和迭代器访问。
Set存储无序、不可重复的元素,只能通过迭代器访问。
ArrayList和LinkedList
ArrayList基于动态数组,需要存储在连续的内存中,适合下标访问(随机访问),不适合插入、删除,适合查询。
扩容机制:因为数组长度固定,超出数组长度时需要新建数组,然后将老数组的数据拷贝到新数组。
插入:如果不是尾插法,后面的元素全部要向后移动,所以使用尾插法并且规定较大的初始长度可以极大提升性能。
LinkedList基于链表,可以存储在分散的内存中,适合数据插入、删除,不适合查询。
插入:需要创建node对象。
遍历:只能使用迭代器,不能使用for循环,不能使用indexOf返回元素索引。因为会对LinkedList全部遍历一遍。
HashMap和HashTable
HashMap是线程不安全的,HashTable是线程安全的,HashTable的方法都是synchronized修饰的。
底层是通过数组+链表实现的。
实现一个ioc容器
1.在配置文件中配置包扫描路径。
2.递归包扫描获取.class文件。
3.反射,确定需要交给ioc管理的类。
4.对需要进行注入的类进行依赖注入。
jvm体系结构

static
static修饰的方法和类一起加载,
没有static的方法和对象一起加载
常见设计模式
单例模式:类只有一个实例,自己实例化自己,提供对外的接口
工厂模式:创建者和调用者分离
mvc模式:model,view,controller
1.spring
控制反转ioc
在配置文件里配置bean和相关属性,让spring容器生成和管理对象,调用set方法而不是new
面向切面aop
将一些功能从逻辑中独立出来,通过运行期间动态代理来实现这些功能
2.springMVC
model模型
数据承载bean如实体类
业务处理bean如service类
view视图 和用户交互的界面
controller控制器
将用户请求转发给相应的model进行处理
处理model的计算结果并返回给用户
3.MyBatis
mapper或注解映射到数据库
4.springboot
简化spring
sleep和wait的区别
sleep指定时间唤醒,wait可以指定时间或者被其他线程用notify或notifyAll唤醒
sleep释放cpu执行权不释放同步锁,wait释放cpu执行权也释放同步锁,同步锁就是synchronized
浙公网安备 33010602011771号