1.Thread与CompletableFuture
Thread主要解决并发,即同时处理多任务
CompletableFuture是异步,即不需等待,有结果后获取结果
CompletableFuture也是通过线程来实现的(可以理解为是Thread的包装),,但是是守护线程(线程池ForkJoinPool),,如果不调用get()方法,可能会在主线程完成时候,守护线程就也结束了,守护线程的程序并不一定可以执行,,因此必须get()
而Thread就不存在这样的问题。
因此Thread比较适用于不需获取结果的操作。
CompletableFuture包装了很多新特点,最重要的是任务加任务,形成一个任务调用链;而Thread就是比较简洁
2.创建线程池的方式
java中创建线程池的方式一般有两种:
- 通过Executors工厂方法创建
- 通过new
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)自定义创建 (推荐)
推荐的创建线程池的方式:
在项目中一定要注意线程池的使用要严谨,不要使用Executors去直接调用API去创建线程池,要使用ThreadPoolExecutor(阿里内部也明确规定这一点)
原因是这样的处理方式能让我们更加明确线程池的运行规则,规避资源耗尽的风险。
Executors 返回线程池对象的弊端如下:
FixedThreadPool 和 SingleThreadExecutor : 允许请求的队列长度为
Integer.MAX_VALUE,可能堆积大量的请求,从而导致OOM。
CachedThreadPool 和 ScheduledThreadPool : 允许创建的线程数量为
Integer.MAX_VALUE ,可能会创建大量线程,从而导致OOM。
原文链接:https://blog.csdn.net/qq_43012792/article/details/106649740
ThreadPoolExecutor原理
有请求时,创建线程执行任务,当线程数量等于corePoolSize时,请求加入阻塞队列里,当队列满了时,接着创建线程,线程数等于maximumPoolSize。 当任务处理不过来的时候,线程池开始执行拒绝策略。