java 线程、进程及相关知识点 《笔记一》
一、线程、进程
线程,就是是进程的一个单位,程序最小执行单位。 进程,就是一个执行中的应用程序;由此可见,进程是由很多线程组成的;
线程生命周期,就是管杀也管埋的过程,生老病死;
线程的5个状态:
新建状态,可执行状态,执行状态,阻塞状态,死亡状态; 可以理解为生老病死:生:创建,老(成长过程):可执行,执行状态,病:阻塞,死:死亡状态; 个人的一点理解和记忆;以下借用别人的一张图来理解下:
大致过程,就是如此,新建线程后,就是一个对象,我们暂且叫他小三子,然后小三子去等待被叫,等到CPU说,小三子到你了,来开始,一声令下,她就开始跑了,正直青春期生命力顽强,你可以让她阻塞,也可能因为其他原因,被抢,开始生病阻塞,这时随时可能又被叫醒,如果加了锁或其他的,他可能会去加入队列等待被执行,等一系列,循环或等待后,执行了自己的任务完成后,这个线程也就等着老死了,一生结束;
二、并发和并行的一点理解
这里借用一个图,或许你一下子就理解了(本人也是这么理解的):Erlang 之父 Joe Armstrong 用一张5岁小孩都能看懂的图解释了并发与并行的区别
由上图可见:并发是两个或两个以上,同时交替使用一个咖啡机,一台咖啡机为多个人服务;并行是,两个咖啡机,同时为每个队伍服务; 重点看,是不是一个多多个主机cpu的服务;
以上,对线程,进程有个初步理解的理论基础知识,知道即可,在实际应用中,是理解部分的知识;
三、线程池的概念
线程使用过程中,创建,执行,销毁,都是消耗内存的,不能无休止的创建线程等等,这就需要我们来管理这些线程,那么管理这些线程我们就可以理解为我们暂且创建一个池子,池子中有我们的线程,这样我们就会来管理他,这种概念我们成为线程池;
Executor框架是java中的线程池实现,在java的API中我们可以看到下面的结构:
void execute(Runnable command);
,只能提交Runnable形式的任务,不支持提交Callable带有返回值的任务。以下是java源码,看到作者了吗,不知道可以去查,jdk1.5开始;
2、 ExecutorService 继承了Executor ,在Executor的基础上加入了线程池的生命周期管理,进入源码我们可以看到,有shutdown或者shutdownNow方法来关闭我们的线程池。ExecutorService支持提交Callable形式的任务,提交完Callable任务后我们拿到一个Future,它代表一个异步任务执行的结果。关于shutdown和shutdownNow方法我们需要注意的是:这两个方法是非阻塞的,调用后立即返回,不会等待线程池关闭完成。如果我们需要等待线程池处理完成再返回可以使用ExecutorService#awaitTermination来完成。
3、ThreadPoolExecutor:是线程池中最核心的类,我么创建线程池一般就是用它;当然这是java为我们提供的,另外一个常用的spring也为我们提供了一个 ThreadPoolTaskExecutor注意区分;
1、corePoolSize:线程池的核心线程数目,核心线程,只是在没有用的时候,也不会被回收;
2、maximumPoolSize就是线程池中可以容纳的最大线程的数量;
3、keepAliveTime 当大于corePoolSize 数量,小于maximumPoolSize 最大线程数,他就会起作用,核心线程即使在无任务的情况下也不能被清除,其余的都是有存活时间的,意思就是非核心线程可以保留的最长的空闲时间,workQueue,就是等待队列,任务可以储存在任务队列中等待被执行,执行的是FIFIO原则(先进先出)超过这个空闲时间空闲线程将被回收;
5、任务进来时,首先执行判断,判断核心线程是否处于空闲状态,如果不是,核心线程就先就执行任务,如果核心线程已满,则判断任务队列是否有地方存放该任务,若果有,就将任务保存在任务队列中,等待执行,如果满了,在判断最大可容纳的线程数,如果没有超出这个数量,就开创非核心线程执行任务,如果超出了,就调用handler实现拒绝策略。
6.拒绝策略:
有四种:第一种AbortPolicy:不执行新任务,直接抛出异常,提示线程池已满
第二种DisCardPolicy:不执行新任务,也不抛出异常
第三种DisCardOldSetPolicy:将消息队列中的第一个任务替换为当前新进来的任务执行
第四种CallerRunsPolicy:直接调用execute来执行当前任务
四种厂家线程池:
CachedThreadPool:可缓存的线程池,该线程池中没有核心线程,非核心线程的数量为Integer.max_value,就是无限大,当有需要时创建线程来执行任务,没有需要时回收线程,适用于耗时少,任务量大的情况。
SecudleThreadPool:周期性执行任务的线程池,按照某种特定的计划执行线程中的任务,有核心线程,但也有非核心线程,非核心线程的大小也为无限大。适用于执行周期性的任务。
SingleThreadPool:只有一条线程来执行任务,适用于有顺序的任务的应用场景。
FixedThreadPool:定长的线程池,有核心线程,核心线程的即为最大的线程数量,没有非核心线程