1.线程初始化的4种方式
1).继承Thread
2).实现Runnable接口
3).实现callable接口+futureTask(可以拿到返回结果,可以处理异常)
4).线程池
2.四种方式对比(在开发场景下)
方式 1 和方式 2:主进程无法获取线程的运算结果。不适合开发场景
方式 3:主进程可以获取线程的运算结果,但是不利于控制服务器中的线程资源。可以导致服务器资源耗尽。
//submit和 execute的区别
//callable和runnable的区别
//(ExecutorService)
1.创建线程池的两种方式
//创建固定数量线程的线程池,最好保证当前系统中只保持一两个,每个异步任务交给线程池,让他自己去执行
Executors.newFiexedThreadPool(3);
//或者
new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit unit,
workQueue, threadFactory, handler);
通过线程池性能稳定,也可以获取执行结果,并捕获异常。但是,在业务复杂情况下,一 个异步调用可能会依赖于另一个异步调用的执行结果。
2.线程池的七大参数
@param corePoolSize
the number of threads to keep in the pool, even if they are idle, unless {@code allowCoreThreadTimeOut} is set
池中一直保持的线程的数量,即使线程空闲。除非设置了 allowCoreThreadTimeOut
@param maximumPoolSize
the maximum number of threads to allow in the pool
池中允许的最大的线程数
@param keepAliveTime
when the number of threads is greater than the core, this is the maximum time that excess idle threads
will wait for new tasks before terminating.
当线程数大于核心线程数的时候,线程在最大多长时间没有接到新任务就会终止释放,
最终线程池维持在 corePoolSize 大小
@param unit
the time unit for the {@code keepAliveTime} argument 时间单位
@param workQueue
the queue to use for holding tasks before they are executed. This queue will hold only the {@code Runnable}tasks submitted by the {@code execute} method.阻塞队列,用来存储等待执行的任务,如果当前对线程的需求超过了 corePoolSize大小,就会放在这里等待空闲线程执行。
@param threadFactory
the factory to use when the executor creates a new thread创建线程的工厂,比如指定线程名等
@param handler
the handler to use when execution is blocked because the thread bounds and queue capacities are reached
拒绝策略,如果线程满了,线程池就会使用拒绝策略。
3.运行流程
1、线程池创建,准备好 core 数量的核心线程,准备接受任务
2、新的任务进来,用 core 准备好的空闲线程执行。
(1) 、core 满了,就将再进来的任务放入阻塞队列中。空闲的 core 就会自己去阻塞队
列获取任务执行
(2) 、阻塞队列满了,就直接开新线程执行,最大只能开到 max 指定的数量
(3) 、max 都执行好了。Max-core 数量空闲的线程会在 keepAliveTime 指定的时间后自
动销毁。最终保持到 core 大小
(4) 、如果线程数开到了 max 的数量,还有新任务进来,就会使用 reject 指定的拒绝策
略进行处理
3、所有的线程创建都是由指定的 factory 创建的。
new LinkedBlockingDequeue<>()默认是Integer的最大值
面试:
一个线程池 core 7**;** max 20 ,queue 50,100** 并发进来怎么分配的;
先有 7 个能直接得到执行,接下来 50 个进入队列排队,在多开 13 个继续执行。现在 70 个
被安排上了。剩下 30 个默认拒绝策略。
4.常见的四种线程池
newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若
无可回收,则新建线程。 (core是0,所有都可以回收)
newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。(所有线程都不可以回收)
newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务
按照指定顺序(FIFO, LIFO, 优先级)执行。