程序:含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中
线程:是一个比进程更小的执行单位,进程执行的过程中可以产生多个线程
进程:程序的一次执行过程,系统运行程序的基本单位
系统运行一个程序即是一个进程从创建,运行到消亡的过程
生命周期:新建、就绪、运行、堵塞、死亡
状态:新建、可运行、堵塞、无限等待、计时等待、死亡
线程安全的本质应该是内存安全,堆是共享内存,可以被所有线程访问
线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复使用
可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃
降低资源消耗,提高线程利用率
提高响应速度
提高线程的可控性
常用线程池:
单线程线程池
固定大小线程池
可缓存线程池
大小无限的线程池
线程数量
线程最大数量
最大空闲时间
时间单位
任务队列
线程工厂
拒绝策略(当任务队列满了,再加入任务时就会执行该策略)
拒绝策略:
直接抛出异常(默认)
直接丢掉任务
将最先进入工作队列等待的任务丢弃,然后接受新的任务
谁调用了本线程池,则谁来执行该任务,保证的任务不会丢失
判断线程池里的核心线程是否都是在执行任务,如果不是则新建线程来执行任务
判断线程池工作队列是否已满,如果已满,进入下一流程
判断线程池中线程是否属于工作状态,如果不是则新建线程来执行任务
当两个线程相互等待对方释放资源时,就会发生死锁;
如何避免:
避免多次锁定
具有相同的加锁顺序
使用定时锁
死锁检测
volatile:能保证可见性和一定程度的顺序性,一个共享变量被volatile修饰后,就具备了两层语义:保证了不同线程对这个变量进行操作时的可见性和禁止了指令重排序
使用场景:
实时共享变量
开销较低的读-写锁策略
单例模式双重检查
ThreadLocal:是一个线程的局部变量,会为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,将对象的可见范围限制在同一个线程内,而不会影响其它线程所对应的副本。
使用场景:
数据库连接
session管理
ThreadLocal里面使用了一个存在弱引用的map, map的类型是ThreadLocal.ThreadLocalMap. Map中的key为一个threadlocal实例
位置不同,synchronized修饰方法、代码块;volatile修饰变量
作用不同,synchronized保证原子性,但可能会造成堵塞;volatile不能保证原子性,但不会造成堵塞
有序性:程序执行的顺序按照代码的先后顺序执行
原子性:一个或多个操作,要么全部执行要么全部不执行
可见性:当一个线程修改了共享变量的值,其他线程能够看到修改的值
并发:同一时间段内,多条指令在cpu上同时执行
并行:同一时刻,多条指令在cpu上同时执行
串行:一次执行一个任务,执行完成,才可继续执行其他任务
分布式是以缩短单个任务的执行时间来提升效率,而集群则是通过提高单位时间内执行的任务数来提升效率。
集群主要分为:高可用集群、负载均衡集群、科学计算集群
分布式是指将不同的业务分布在不同的地方,集群指几台服务器集中在一起,实现同一业务;分布式中每个节点都可以做集群,而集群并不一定是分布式的。
管道
消息队列
信号量
内存共享
套接字
继承Thread接口
实现Runnable接口
使用Callable和Future
使用线程池
程序正常运行结束
使用自定义标志退出线程(定义volatile修饰的关键字,当关键字为true时循环退出)
使用Interrupt方法结束线程
使用stop方法终止线程(不推荐,线程不安全)
乐观锁:认为多线程同时修改共享资源的概率比较低,它假定冲突的概率很低,它的工作方式是:先修改完共享资源,再验证这段时间内有没有发生冲突,如果没有其他线程在修改资源,那么操作完成,如果发现有其他线程已经修改过这个资源,就放弃本次操作。
悲观锁:比较悲观,认为多线程同时修改共享资源的概率比较高,于是很容易出现冲突,所以访问共享资源前,先要上锁
自旋锁:尝试获取锁的线程不会立即阻塞,而是采⽤循环的方式去尝试获取
互斥锁:只有一个线程能够访问被互斥锁保护的资源;在访问共享对象之前,对其进行加锁操作。在访问完成之后进行解锁操作
可重入锁:以线程为单位,当一个线程获取对象锁之后,这个线程可以再次获取本对象上的锁,而其他的线程是不可以的
可以保留住想要继续入队的任务
当没有任务时,可以释放cpu资源
无任务时,线程挂起,不占用cpu资源
核心原理在于线程池对 Thread 进行了封装,并不是每次执行任务都会创建新线程,而是让每个线程去执行一个“循环任务”,在这个“循环任务”中,不停地检查是否还有任务等待被执行,如果有则直接去执行这个任务,也就是调用任务的 run 方法,把 run 方法当作和普通方法一样的地位去调用,相当于把每个任务的 run() 方法串联了起来,所以线程数量并不增加。
Lock:阻塞加锁,无返回值,如果该线程没偶遇获得锁就阻塞,直到获得锁才放开
tryLock:尝试加锁,可能加到也可能加不到,该方法不会阻塞线程,加到锁才返回true否则返回false;利用tryLock可以有自旋锁,自旋锁相对灵活,但对cpu消耗大,性能优于lock。
sleep():使线程进入堵塞状态,指定时间内不执行,释放CPU资源但不释放锁标志
wait():释放CPU资源,同时释放锁,进入等待状态
Join():使线程进入堵塞状态,不释放锁标志
yieId():使线程进入就绪状态,释放CPU资,等待重新执行
Runnable通过继承Thread实现,还可以实现多个接口
Runnable是接口,而Thread是类
Runnable支持多线程间的资源共享
也叫后台线程,为所有非守护线程提供服务;守护线程必须可以随时关闭;如果想设置守护线程,必须在start()方法之前设定;不能把正常运行的线程设置为守护线程。
如:GC垃圾回收线程
start方法来启动线程;run只是thread内的普通方法
需要并行处理的代码放在run方法中;start方法启动线程后自动调用run方法
run必须为public,返回类型为void
aop指的是切面,将程序中的交叉业务逻辑,封装成一个切面,然后注入到目标对象中去。
ioc容器:实际上就是一个map,里面存对象,启动时读取
控制反转:获取对象的过程颠倒过来,对象的控制权力全部上交给了ioc容器,起到了粘合的作用。
依赖注入:获得依赖对象的过程由自身管理变成了ioc容器注入,在运行期间,动态的将依赖关系注入到对象。
单例:默认,每个容器只有一个bean实例,由BeanFactory自身来维护;
原型:容器中就有多个实例,每个bean都会有一个实例,每次注入都会创建新的实例
Request:每个http请求创建一个单例对象,单个请求中复用
Session:每个session都有一个bean,session过期,bean失效
application:生命周期内复用一个单例对象
websocket:生命周期内复用一个单例对象
多个事务方法相互调用,事务如何在这些方法间传播?
如果有就加入,如果没有事务,就创建一个;
如果有就加入,如果没有事务,就以非事务方法执行
如果有就加入,如果没有事务,就抛出异常
创建一个新事务,如果有就挂起
以非事务方法执行,如果有就挂起
不使用事务,如果存在,抛出异常
如果存在,就嵌套在事务中执行
发生自调用,类里面用this调用本类方法
方法不是public
数据库不支持事务
没有被spring管理
抛出异常,事务没有回滚
解析类得到BeanDefinition
如果有多个构造方法,则要推断构造方法
确定好构造方法后,进行实例化得到第一个对象
对象中添加@Autowired注解进行填充
回调Aware方法
调用BeanPostProcessor的初始化前的方法
调用初始化方法
调用BeanPostProcessor的初始化后的方法
把bean放入单例池
使用bean
关闭时调用destory方法
如果bean无状态,则是安全的
如果bean有状态,则是不安全的
都是bean容器;
ApplicationContext是BeanFactory的子接口
ApplicationContext提供了更完整的功能
ApplicationContext更占用空间
BeanFactory以编程的方式创建,ApplicationContext还能以申明的方式创建
事务的实现方式:
1、编程式
2、申明式
隔离级别:
未提交读:可能看到其他事务中未提交的数据(脏读)
提交读:能读取到已经提交事务的数据(不可重复读)
可重复读:能确保同一事务多次查询的结果一致(幻读)
串行化:强制事务排序,使之不会发生冲突;执行效率低,使用的场景不多
容器初始化
将配置类的BeanDefinition注册到容器中
容器刷新
简单工厂、工厂方法、单例、适配器、包装器、代理、观察者、策略、模板方法
构造方法注入
set方法注入
属性注入
SpringMvc 是 spring 的一个模块,基于 MVC 的一个框架,无需中间整合层来整合
它是基于组件技术
不依赖与servlet
可以使用任何视图
易于拓展
客户端发送请求到前端控制器
前端控制器查询处理器映射器,找到处理请求的 后端控制器
后端控制器调用业务逻辑后,返回视图控制器
前端控制器查询视图控制器,找到指定视图
将视图返回给客户端
1.用户发起请求到前端控制器
2.前端控制器请求处理器映射器去查找处理器
3.找到以后处理器映射器向前端控制器返回
4.前端控制器调用处理器适配器去执行处理器
5.处理器适配器去执行处理器
6.处理器执行完给处理器适配器返回ModelAndView
7.处理器适配器向前端控制器返回ModelAndView
8。前端控制器请求视图解析器去进行视图解析
9.视图解析器像前端控制器返回View
10.前端控制器对视图进行渲染
11.前端控制器向用户响应结果
前端控制器
处理器映射器
处理器适配器
处理器
视图解析器
视图
@Component:泛指各种组件
@Controller:控制层
@Service:业务层
@Repository:数据访问层
@Bean:导入第三方包里面的注解
@Import:导入到容器中的组件
Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在;Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入
是单例模式,所以在多线程访问的时候有线程安全问题,不要用同步,会影响性能的,解决方案是在控制
器里面不能写字段
springboot是spring的子项目,是spring组件的一站式解决方案,简化了使用的难度,简省了配置
优点:
容易上手,提升开发效率
开箱即用,减少配置
没有代码生成,也没有xml配置
避免了大量maven版本冲突
@SpringBootApplication :替代 @SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan
@ImportAutoConfiguration:导入配置类
@SpringBootConfiguration:替代@Configuration
@ImportResource:将资源导入容器
@PropertySource :导入properties文件
@PropertySource :PropertySources的集合
@Autowired:默认按类型装配
注解 @EnableAutoConfiguration, @Configuration, @ConditionalOnClass 就是自动配置的核心,@EnableAutoConfiguration 给容器导入META-INF/spring.factories 里定义的自动配置类。筛选有效的自动配置类。每一个自动配置类结合对应的 xxxProperties.java 读取配置文件进行自动配置功能
使用依赖项,必须添加安全配置
actuator,监视器可帮助访问生产环境中正在运行的应用程序的当前状态
CSRF指的是跨站请求伪造
在pom文件中添加依赖
springboot可以独立建立spring应用程序
内嵌tomcat
无需繁重的xml配置
可以自动配置spring
整合了常用的依赖
打包用命令或者放到容器中运行
用maven插件运行
直接执行main方法
1.properties文件
2.ymal文件
3.系统环境变量
.....