什么是线程池
线程池,顾名思义就是将线程放入一个池子中,在需要时去线程池中取线程,用完之后再把线程放回到池子里
线程池的优点
能够对线程进行管理,防止产生线程过多抢占资源导致堵塞,同时也能避免线程创建和销毁过程中占用的系统开销
线程池的概念
线程池的顶级接口是Executor,真正的线程池接口是ExecutorService,而默认实现的是ThreadPoolExecutor,Executors是一个普通的类,在里面调用了ThreadPoolExecutor
一些接口和普通类的源码
public interface Executor{
void execute(Runnable command);
}
...
public interface ExecutorService extends Executor{
void shutdown();
List<Runnable>shutdownNow();
boolean isShutdown();
boolean isTerminated();
<T>Future<T> submit(Callable<T> task);
<T>Future<T> submit(Runnable task,T result);
Future<?>submit(Runnable task);
...
}
public class Executors{
public static ExecutorService newCachedThreadPool{
return new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,new SynchronousQueue<Runnable>());
}
...
}
线程池的设计思路
当一个任务被放进线程池中,会先查看线程池中核心线程池是否已满,未满就创建一个核心线程池来运行任务,满了就看等待队列是否已满,若等待队列满了则去看最大线程数是否已满,如果都满了则按照拒绝策略来处理任务
采用这种设计思路原因是因为ThreadPoolExecutor在执行execute()方法时,能尽可能的避免全局锁(一次只能进一个任务),这个设计可以让任务在ThreadPoolExecutor预热(创建好核心线程)之后,有很大的机会直接放入队列中等待核心线程的调用
线程池的创建
ExecutorService es=ExeCutors.newCachedThreadPool();
es.submit(放入线程);//有返回值
es.execute(放入线程);//没有返回值
es.shutdown();//将线程池的状态设置成shoutdown状态,然后中断所有没有执行任务的线程
es.shutdownNow();//将线程池的状态设置成stop状态,然后尝试停止所有正在执行的或者暂停的任务的线程,并返回等待执行任务的列表
线程池复用线程原理
public void run(){
try{
Runnable task=firstTask;
firstTask=null;
//如果有一个任务过来就创建一个线程执行任务
//执行完之后去工作队列里取任务继续执行
while(task ! = null || (task = getTask()) ! = null ){
task=null;
}
}finally{
workerDone(this);
}
}
线程池的参数
public ThreadPoolExecutor(int corePoolSize,//核心线程个数
int maximumPoolSize,//最大线程个数
long keepAliveTime,//线程存活时间
TimeUnit unit,//指定存活时间的单位
BlockingQueue<Runnable>workQueue,//线程池的任务队列
ThreadFactory threadFactory,//线程工厂,主要用来创建新线程
RejectExecutionHandler handler//线程池满时的拒绝策略
){
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler);
}
线程池任务队列
1.AbortPolicy 直接抛异常
2.CallerRunsPolicy:只用调用者所在的线程来处理这个任务
3.DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务
4.DiscardPolicy:直接丢弃这个任务 不处理
jdk提供的四种线程池
- newCachedThreadPool()
public static ExecutorService newCachedThreadPool(){
return new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,new SynchronousQueue<Runnable>);
}
可缓存线程池 :该线程池可以根据提交进来的任务多少来自动创建线程,当有空闲线程时,超过60s会终止并从缓存中清除空闲线程,十分适合处理大量的短期异步程序
2.newFixedThreadPool()
public static ExecutorService newFixedThreadPool(int nThreads){
return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}
固定线程池,该线程池可以根据需要来创建固定的核心线程个数和固定的最大线程个数
3.newSingleThreadExecutor()
public static ExecutorService newSingleThreadExecutor(){
return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnabl>()));
}
单例线程池,该线程池里面只有一个线程,只能按照顺序来执行任务
4.newSceduledThreadExecutor()
public ScheduledThreadPoolExecutor(int corePoolSize){
super(corePoolSize,Integer.MAX_VALUE,0,NANOSECONDS,new DelayedWordQueue());
}
固定线程池,该线程池可以定时周期性的执行任务