创建线程
创建线程的3种方式:
1)采用实现Runnable. Callable接口的方式创建多线程。2)使用继承Thread类的方式创建多线程,3)线程池创建
Callable规定(重写)的方法是call(),Runnable规定(重写)的方法是run()。
Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
Call方法可以抛出异常,run方法不可以。
为什么不建议Executors创建线程池?
当我们使用Executors创建线程池会出现什么问题?
1.发现创建的队列为LinkedBlockingQueue,是一个无界阻塞队列,如果使用该线程池执行任务如果任务过多就会不断的添加到队列中,任务越多占用的内存就越多,最终可能耗尽内存,导致OOM。
2.除开有可能造成O0M之外,我们使用Executors来创建线程池也不能自定义线程的名字,不利于排查问题,所以建议直接使用ThreadPoolExecutor来定义线程池,这样可以灵活控制。
shutdown() VS shutdownNow()
1.shutdown() :关闭线程池,线程池的状态变为 SHUTDOWN。线程池不再接受新任务了,但是队列里的任务得执行完毕。
2.shutdownNow() :关闭线程池,线程的状态变为 STOP。线程池会终止当前正在运行的任务,并停止处理排队的任务并返回正在等待执行的 List。shutdownNow的原理是遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程,所以无法响应中断的任务可能永远无法终止
isTerminated() VS isShutdown()
1.isShutDown 当调用 shutdown() 方法后返回为 true。
2.isTerminated 当调用 shutdown() 方法后,并且所有提交的任务完成后返回为 true
执行execute()方法和submit()方法的区别是什么呢?
execute() 方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功与否;
submit()方法用于提交需要返回值的任务。线程池会返回一个future类型的对象,通过这个future对象可以判断任务是否执行成功
如果你提交任务时,线程池队列已满,这时会发生什么
1如果使用的无界队列,那么可以继续提交任务时没关系的(定义是无界的,实际还是有界)
2如果使用的有界队列,提交任务时,如果队列满了,如果核心线程数没有达到上限,那么则增加线程,如果线程数已经达到了最大,则使用拒绝策略进行拒绝
线程池的5种状态
RUNNING
线程池正常运行,能处理任务,能接收任务
SHUTDOWN
当调用线程池的shutdown方法时,线程池就进入SHUTDOWN状态,表示线程池处于正在关闭状态,此状态下线程池不会接受新任务,但是会继续把队列中的任务处理完
STOP
当调用线程池的shutdownnow方法时,线程池就进入STOP状态,表示线程池处于正在停止状态,此状态下线程池既不会接受新任务了,也不会处理队列中的任务,并且正在运行的线程也会被中断
TIDYING
线程池中没有线程在运行后,线程池的状态就会自动变为TIDYING,并且会调用terminated该方法是空方法,留给程序员进行扩展。
TERMINATED
terminated方法执行完之后,线程池状态就会变为TERMINATED
线程池参数
corePoolSize : 核心线程大小。线程池一直运行,核心线程就不会停止。
maximumPoolSize :线程池最大线程数量。非核心线程数量=
maximumPoolSize-corePoolSize
keepAliveTime :非核心线程的心跳时间。如果非核心线程在keepAliveTime内没有运行任务,非核心线程会消亡。
unit :是指空闲线程存活时间的单位。keepAliveTime的计量单位。枚举类型TimeUnit类。
workQueue :阻塞队列。
ArrayBlockingQueue :有界阻塞队列FIFO
LinkedBlockingQueue :无界阻塞队列FIFO
PriorityBlockingQueue :优先级无界阻塞队列,非FIFO
SynchronousQueue :默认非公平模式
defaultHandler :饱和策略。ThreadPoolExecutor类中一共有4种饱和策略。通过实现RejectedExecutionHandler接口。
AbortPolicy : 线程任务丢弃报错。默认饱和策略。
DiscardPolicy : 线程任务直接丢弃不报错。
DiscardOldestPolicy : 将workQueue队首任务丢弃,将最新线程任务重新加入队列执行。
CallerRunsPolicy :线程池之外的线程直接调用run方法执行。
ThreadFactory :线程工厂。新建线程工厂。设置线程名,是否是守护线程,优先级
执行流程
线程池执行任务的流程
本文暂时没有评论,来添加一个吧(●'◡'●)