一.进程和线程的区别
进程是一个应用程序,例如一个微信,而线程就是进程中的最小调度单位,一个进程最少有一个线程,向微信的服务器发的一个请求就是一个线程.
二.线程的创建方式
1.继承Thread类
2.实现Runable接口
3.实现Callable接口
4.线程池
三.线程池的7大参数
1.核心线程数:核心线程数初始为0当我们调用线程池创建一个任务的时候,线程池先判断核心线程有没有满,如果没满就继续判断有没有空闲的核心线程,有就复用,没有就创建一个
2.最大线程数:当阻塞队列和核心线程都满了之后需要判断最大线程数有没有达到,如果没有达到就创建一个临时线程
3.阻塞队列:当核心线程满了之后就将任务加入到阻塞队列
4.存活时间:临时线程的存活时间
5.时间单位:临时线程的存活时间单位
6.线程工厂:创建线程的工厂
7.拒绝策略:当核心线程数,阻塞队列,临时线程数都在工作的时候,这个时候又进来一个新的任务那么就会触发拒绝策略,拒绝策略有四种
7.1:AbortPolicy:丢弃任务并抛出RejectedExecutionException异常.(默认)
7.2:DiscardPolicy:丢弃任务,但是不抛出异常。如果线程队列已满,则后续提交的任务都会被丢弃,且是静默丢弃.
7.3:DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务.
7.4:CallerRunsPolicy:由调用线程处理该任务.
四.面试题
1.继承Thread类和实现Runnable接口,有什么区别?你一般选择哪个?为什么?
继承Thread类可以通过new对象的方式直接调用start方法,而通过实现Runnable接口的方式就需要通过new Thread(实现接口的对象)这样的方式创建一个Thread对象之后调用start方法.
我一般会选择实现Runnable这种方式,因为java是单继承的,如果现在使用了继承,后续可能该类就不方便扩展,所以出于设计上的灵活性考虑,应该使用Runnable
2.实现Runable接口和实现Callable接口有什么区别?
实现Runable接口重写的是run方法,而实现Callable接口重写的是call方法,重写call方法相比run可以有返回值,返回值在futureTask调用get方法获取.
3.介绍一下线程池:参考三
五.线程状态
线程有五种状态:新建、就绪、运行、阻塞、死亡
六.线程安全问题
多线程使用共享数据是不安全的,想要安全就需要加入一些措施
1.Synchronized 2.Lock 它们的区别是:
synchronized是关键字,lock是类.
synchronized报错了会自动释放锁,而lock必须要在finally中unlock因为报错不会自动释放锁,可能会死锁.
synchronized无法判断锁的状态而lock可以通过api判断.
lock可以指定是否公平竞争.
当请求数量变多的时候,lock比synchronized性能好.
synchronized加在普通方法上就相当于对象锁,加在静态方法上就相当于类锁,synchronized底层通过使用 monitorenter(加锁)和 monitorexit(解锁) 指令实现.
悲观锁与乐观锁:悲观锁有Synchronized,Lock,数据库的行锁、表锁,乐观锁有cas,数据库使用version字段
死锁:两段分开的代码 第一段a锁套b锁 第二段b锁套a锁 ,然后当第一个线程执行到ab中间的时候被第二个线程抢占cpu资源去执行第二段代码,然后执行到ba中间的时候就形成了死锁
七.线程之间的通信
1.同步通信:wait、notify、notifyAll,jion方法, volatile 关键字
2.异步通信:消息中间件
3.进程间的通信:http、feign、socket、mq
八.多线程并发
1.原子性:一个线程操作是不能被其他线程打断
2.有序性:线程在执行程序是有序的
3.可见性:一个线程修改数据后,对其他线程是可见的
4.volatile:可以保证内存可见性,和防止指令重排,具体是通过内存屏障实现的,内存屏障会阻止屏障两边的指令重排序,同时对于写操作,强制线程的私有内存中的数据写入到主内存,对于读操作强制从主内存中读取数据到私有内存
volatile写上面有StoreStore屏障:禁止该屏障上方的普通写与下面的volatile写重排序
volatile写下面有StoreLoad屏障:禁止该屏障上面的volitaile写与下面可能有的volatile读/写重排
volatile读下面有LoadLoad屏障:禁止处理器把该屏障上方的volatile读与下面的普通读重排序
LoadLoad屏障下面有LoadStore屏障:禁止处理器把该屏障上的volatile读与下面的普通写重排序.
九.单例模式(双重检查锁)
十.Spring集成线程池
@Async标记在方法上,表示当前方法是异步执行的(使用默认线程池),@EnableAsync开启异步支持