异步JUC
初始化线程的4种方式
- 继承Thread
- 实现Runnable接口
- 实现CallCallable接口+FutureTask(1.5之后出现的 特点:可以拿到返回结果 可以处理异常)
- 线程池
测试不用测试类测试不出多线程的效果
第一种
第二种
第三种
查看futuretask会发现这是一个实现了一个继承Runnable的接口
测试
注意点:这是一个阻塞等待
第四种
整个系统一两个线程池(核心业务的非核心业务的) 而不是一个业务一个池
业务中不会用前面的三种 只会用第四种方式来操作资源达到资源的稳定性
有参数的对应第3种
无参数的对应第1,2种
直接new一个已创建好的线程传入进去即可
小结:
线程池的详细介绍
给线程池直接提交任务
1.创建:则ExecutorService就是线程池
-
直接使用Executors工具类
-
new ThreadPoolExecutor();
可传递参数
原生线程池里面的七大参数:
int corePoolSize:核心线程数[一直存在除非设置了allowCoreThreadTimeOut];线程池创建好以后就准备就绪的线程数量,就等待来接受异步任务去执行 new Thread(); 提交任务的时候就会执行空的线程 即thread.start
int maximumPoolSize:最大线程数量;作用是控制资源
long keepAliveTime:存活时间。如果当前正在运行的线程数量大于core数量。释放空闲的线程(maximumPoolSize-corePoolSize),只要线程大于指定的long keepAliveTime就会直接释放资源,避免资源浪费
TimeUnit unit:时间单位(存活时间的时间单位)
BlockingQueue workQueue:阻塞队列,如果任务有很多,就会将目前多的任务放到对列里边只要有线程空闲,就会去队列里面取出新的任务继续执行。
ThreadFactory threadFactory:线程的创建工厂,线程有自己的名字约束,就可以用工厂来创建线程
RejectedExecutionHandler handler:如果队列满了,按照我们指定的拒绝策略拒绝执行任务
工作的顺序:
再次说明
- 线程池创建,准备好core数量的核心线程,准备接受任务
1.1 core满了,就将再进来的任务放入到阻塞队列中,空闲的core就会自己去阻塞队列获取任务执行
1.2 阻塞队列满了,就直接开新的线程执行,最大只能开到max(int maximumPoolSize)指定的数量
1.3 max满了就用RejectedExecutionHandler拒绝任务
1.4 max都执行完成,有很多空闲,在指定的时间(keepAliveTime)以后 ,释放max-core这些线程
1.5 BlockingQueue的解释:传递的参数是这个队列类型
这队列的取值范围默认是Integer的最大值 内存不够直接占满 (一般是压力测试的系统峰值的数量)
1.6 threadFactory的说明:Executors.defaultThreadFactory(使用juc包下的api来创建默认的线程工厂)
1.7RejectedExecutionHandler
1.8完成创建
1.9面试题
按照同步的方式来执行
线程池API Executors
1
无核心的线程
2.
3.new ScheduleExecutorService()
4.
总结:
线程池的好处
又一问题的出现:
当A B C三个线程要有先后顺序或者关系,比如说C的执行的返回结果A要用这么来保证线程的顺序呢?
Completable和Future异步编排
业务场景
这相当于vue的promise可以异步编排ajax请求
注意这些方法里面都是关联的函数式接口()
Future怎么和FutureTask关联起来的
Future最大的特点就是能够获取到异步的结果
创建对象
前面两个没有返回值
后面的是有返回值得
测试