线程池
线程的生命周期
线程的创建时间、线程的执行时间、线程的销毁时间
线程三大主要开销
- Java 的线程模型是基于操作系统原生线程模型实现的,即是基于内核线程实现的;线程的创建,析构与同步都需要进行系统调用,在用户态和内核态切换开销大;
- 每个线程都需要一个内核线程的支持,也就会消耗一定的内核栈空间,故能创建的线程数是有限的;
- 若线程数量过多,则会导致频繁的上下文切换;
线程的状态
新建、 可运行(就绪/运行中)、 阻塞(请求获取锁)、 等待(io事件)、 定时等待(sleep)、 终止
创建线程
- 线程调度是由系统控制的,程序员不可能精准的去干涉它;
- 核心本质:new Thread()
class myThead extends Thread {
// 重写run方法
public void run() {
// do something here
}
}
public static void main(String[] args){
myThead oneThread = new myThread();
// 启动线程:自动执行run方法
oneThread.start();
}
class SomeRunnable implements Runnable {
// 重写run方法
public void run() {
//do something here
}
}
// 创建Runnable实现类的实例,并以此实例作为Thread的target对象,即该Thread对象才是真正的线程对象。
Runnable oneRunnable = new SomeRunnable();
Thread oneThread = new Thread(oneRunnable);
oneThread.start();
线程池提交任务与执行任务
线程池创建
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 60, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>());
注
- 阻塞队列一定是要有界的,否则会导致拒绝策略失效
- 核心线程数:也称最小线程数
- 最大空闲时间:针对的是超过核心线程数之后的线程 (如果现在核心线程数为10,但当前只有3个线程,即使超过了最大空闲时间,该线程也不会被销毁)
拒绝策略
- CallerRunsPolicy - 当触发拒绝策略,只要线程池没有关闭的话,则使用调用线程直接运行任务。一般并发比较小,性能要求不高,不允许失败。但是,由于调用者自己运行任务,如果任务提交速度过快,可能导致程序阻塞,性能效率上必然的损失较大
- AbortPolicy - 丢弃任务,并抛出拒绝执行 RejectedExecutionException 异常信息。线程池默认的拒绝策略。必须处理好抛出的异常,否则会打断当前的执行流程,影响后续的任务执行。
- DiscardPolicy - 直接丢弃,其他啥都没有
- DiscardOldestPolicy - 当触发拒绝策略,只要线程池没有关闭的话,丢弃阻塞队列 workQueue 中最老的一个任务,并将新任务加入
线程池提交任务
// 方式一:execute 方法(无返回值、无法捕获异常)
public void execute(Runnable command) {
}
// 方式二:ExecutorService 中 submit 的三个方法(有返回值、可以捕获异常)
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
Demo实战
https://www.cnblogs.com/ReturnOfTheKing/p/17989174
并发
Synchronized
- 用于锁住方法或者代码块;锁代码块时可以是synchronized(this){}、synchronized(Object){}、synchronized(类class){}
- 自动获得锁、自动释放锁
- 当对象是同一个时,锁才会起作用
- 保证了同一个时刻某段代码只能由一个线程执行
synchronized(this){
// 锁住该类的对象
// 若修饰静态方法,则锁住该类的所有对象
// 当参考对象相同时,同步锁才起作用,否则锁不会互斥
}
ReentrantLock
TODO
参考链接
Async注解
参考文章
作用
使加上该注解的类或方法能够异步执行任务
参数
value参数:指定线程池
注解无效的可能情况
- 没有加@EnableAsync注解
- @Async修饰的方法不是public方法
- @Async修饰的方法被static修饰了
- 调用方法和@Async方法在同一个类中
- @Async修饰的方法的返回值不是void或Future
线程池和连接池的区别
- MySQL连接池关注于对数据库资源(数据库连接对象)进行管理,而线程池关注于对多线程资源(线程对象和CPU等计算机资源)进行管理;
参考文章
【1】https://mp.weixin.qq.com/s/smfDcR-fjSlbvbvBXp1WMA
【2】https://www.cnblogs.com/snow-flower/p/6114765.html
【3】线程池参数配置