创建线程的4种方法(https://blog.csdn.net/Sophiahaha/article/details/93534072)推荐使用线程池来创建线程因为线程的创建与销毁,阻塞与唤醒都是要从用户态转到内核态来完成。这样性能消耗比较大。
处理程序分为两类:计算、I/O处理(阻塞程序)
使用线程池的三个优点如下:
1. 降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁带来的消耗。
原来的线程在run方法执行完毕后就被销毁了 ,如果一个任务需要多次执行,就是创建了多个线程,又多次销毁了
2. 提高响应速度:当任务到达时,任务可以不需要等待线程创建就能立即执行。
由于线程池中有若干个已经创建好的线程,不需要等待线程创建的时间
3. 提高线程的可管理性:使用线程池可以统一进行线程分配、调度和监控。
因为所有线程都在一个线程池对象中,通过这一个对象进行进行线程分配、调度和监控。
Public interface Executor
Public interface ExecutorService extends Executor
Public interface ScheduledExecutorService extends ExecutorService
Public abstract class AbstractExecutorService implements ExecutorService
Static class DelegatedExecutorService extends AbstractExecutorService
Static class DelegatedScheduledExecutorService extends DelegatedExecutorService
implements ScheduledExecutorService
Static class FinalizableDelegatedExecutorService extends DelegatedExecutorService
Public class ForkJoinPool extends AbstractExecutorService
Public class ScheduledThreadPoolExecutor extends ThreadPoolExecutor implements ScheduledExecutorService
Static final class ThreadPerTaskExecutor implements Executor
Public class ThreadPoolExecutor extends AbstractExecutorService
线程池的核心两大接口
1、ExecutorService:普通线程池
任务提交到线程池execute(),submit()方法
voidexecute(Runnablecommand);接受Runnable对象,执行runnable任务(Executor接口中的)
<T>Future<T>submit(Callable<T>task); 既可以接受runnable,又可以接受callable,可返回值
<T>Future<T>submit(Runnabletask,Tresult);
Future<?>submit(Runnabletask);
2、ScheduledExecutorService:定时线程池
Public ScheduledFuture<?>scheduleAtFixedRate(
Runnable command,long initialDelay,long period,TimeUnit unit);
线程池的两大核心类
ThreadPoolExecutor是ExecutorService普通线程池的子类
构造方法之一
Public ThreadPoolExecutor(int corePoolSize, //线程数量
int maximumPoolSize,
long keepAliveTime, //生存时间,如果10分钟没干一件事,就把他销毁了,只收最大线程池的,和新线程池并不回收
TimeUnit unit,
BlockingQueue<Runnable> workQueue
RejectedExecutionHandler handler
)
线程池工作流程
当一个任务抵达线程池,需要在线程池调用submit或者executor来执行这个任务时
当一个任务提交给线程池时,
1、首先判断核心池的线程数量是否达到corePoolSize,
若为达到,线程池创建新的线程执行任务它并将其置入核心池
否则,判断核心池是否有空闲线程,
若有,将线程分配去执行任务
否则进入步骤2
2、(状态:此时线程数量达到核心池数量,并且没有空闲线程)
判断当前线程池中线程数量有没有达到线程池的最大数量maximumPoolSize,
若没有,创建新的线程执行任务并将其置入线程池中,
否则,进入步骤3
3、(状态:此时线程数量达到核心池数量;线程池中线程数量满,)
判断阻塞队列是否已满,
若未满,将任务置入阻塞队列中等待调度。
否则,进入步骤4
4、(状态:此时线程数量达到核心池数量;线程池中线程数量满;阻塞队列满)
调用相应的拒绝策略打回任务(有四种拒绝策略,默认为抛出异常给用户AbortPolicy)
核心线程池corePool
最大线程池maximumPool
阻塞队列
打回策略
当向线程池提交了一个任务之后,线程池是如何处理这个任务的呢?下面来看线程池的主要处理流程如下:
1)线程池判断核心线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行任务。如
果核心线程池里的线程都在执行任务,则进入下个流程。
2)线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果
工作队列满了,则进入下个流程。
3)线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已
经满了,则交给饱和策略来处理这个任务。