1、什么是线程,线程和进程的区别是什么
程序执行流最小单位。一个请求到系统会启动一个线程。
一个进程一般包含多个线程,线程是实际运行的任务执行者。
2、线程中的基本概念,线程的生命周期
1、线程创建后 ——> 进入就绪状态(Runnable 可运行的)
后面看图1、2
3、单线程和多线程
单线程
多线程:创建多条线程同时执行任务
并行:同一时间执行多个任务,一定是同时
并发:处理多任务的能力,不一定同时,多核可以同时
多线程并发:多线程处理任务,并且有用到共享资源,就要考虑多线程并发问题。
4、怎么处理多线程并发问题
5、线程池的原理解析
1、最重要的类:
Executor :线程池类,是接口
ThreadPoolExecutor : 线程池接口(Executor )的子类
ThreadPoolExecutor 最重要的构造函数:
public ThreadPoolExecutor(
int corePoolSize, //核心线程数,不会被回收的线程数
int maximumPoolSize, //最大线程数
long keepAliveTime, // 除了核心线程外其他线程空闲最长保留时间
TimeUnit unit, // 计算keepAliveTime 时间的单位
BlockingQueue<Runnable> workQueue, // 任务等待队列,FIFIO原则(先进先出)
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler // 拒绝策略,任务满的时候拒绝某些任务
)
2、ThreadPoolExecutor 的使用
使用:https://www.cnblogs.com/dafanjoy/p/9729358.html
3、其他实现类:
他们的实现都是调用 ThreadPoolExecutor 实现
newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
具体使用:Java 四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor - 星辰之力 - 博客园
4、为什么要用线程池、什么时候用线程池?
每个请求都会对应一个线程,线程的创建、销毁对系统资源的开销比较大。JVM 中如果创建过多的线程,容易造成系统资源紧张或者系统崩溃。
在线程生命周期过程中,创建线程、切换线程状态、终结线程,都要进行CPU调度。这些操作都需要耗费CPU资源
6、线程池处理流程
任务进来时,首先执行判断,判断核心线程是否处于空闲状态,如果不是,核心线程就先就执行任务,如果核心线程已满,则判断任务队列是否有地方存放该任务,若果有,就将任务保存在任务队列中,等待执行,如果满了,在判断最大可容纳的线程数,如果没有超出这个数量,就开创非核心线程执行任务,如果超出了,就调用handler实现拒绝策略。
7、有效使用线程池使用准则
只要您遵循几条简单的准则,线程池可以成为构建服务器应用程序的极其有效的方法:
(1)不要对那些同步等待其它任务结果的任务排队。这可能会导致上面所描述的那种形式的死锁,在那种死锁中,所有线程都被一些任务所占用,这些任务依次等待排队任务的结果,而这些任务又无法执行,因为所有的线程都很忙。
(2)在为时间可能很长的操作使用合用的线程时要小心。如果程序必须等待诸如 I/O 完成这样的某个资源,那么请指定最长的等待时间,以及随后是失效还是将任务重新排队以便稍后执行。这样做保证了:通过将某个线程释放给某个可能成功完成的任务,从而将最终取得 某些 进展。
理解任务。要有效地调整线程池大小,您需要理解正在排队的任务以及它们正在做什么。它们是 CPU 限制的(CPU-bound)吗?它们是 I/O 限制的(I/O-bound)吗?您的答案将影响您如何调整应用程序。如果您有不同的任务类,这些类有着截然不同的特征,那么为不同任务类设置多个工作队 列可能会有意义,这样可以相应地调整每个池。
8、handler的拒绝策略
有四种:
第一种AbortPolicy:不执行新任务,直接抛出异常,提示线程池已满
第二种DisCardPolicy:不执行新任务,也不抛出异常
第三种DisCardOldSetPolicy:将消息队列中的第一个任务替换为当前新进来的任务执行
第四种CallerRunsPolicy:直接调用execute来执行当前任务
9、常见的几种线程池的特点以及各自的应用场景
CachedThreadPool:可缓存的线程池,该线程池中没有核心线程,非核心线程的数量为Integer.max_value,就是无限大,当有需要时创建线程来执行任务,没有需要时回收线程,适用于耗时少,任务量大的情况。
SecudleThreadPool:周期性执行任务的线程池,按照某种特定的计划执行线程中的任务,有核心线程,但也有非核心线程,非核心线程的大小也为无限大。适用于执行周期性的任务。
SingleThreadPool:只有一条线程来执行任务,适用于有顺序的任务的应用场景。
FixedThreadPool:定长的线程池,有核心线程,核心线程的即为最大的线程数量,没有非核心线程
10、Java 代码怎么创建线程
Java线程面试题合集(含答案)_Tanyboye的博客-CSDN博客_线程面试题