标签:java 线程池原理
使用线程池的好处:
1.降低资源消耗:减少了线程创建和销毁的资源消耗
2.提高响应速度,当任务到达时,线程可以不尽兴创建直接处理
3.提高线程的可管理性。使用线程池可以对线程进行统一的管理,监控,使用。
线程池的源码分析:
public void execute(Runnable command){
if(command==null){
throw new NullPointerException();
}
//如果执行线程数小于基本线程,则创建线程,并执行任务
if(poolsize>=corepoolsize||!addifundercoresize(command)){
//如果线程池数量大于等于核心池数量或者线程创建失败,直接放入队列中
if(runstate==runnable&&workQueue.offer(command)){
if(runstate!=runnable||poolsize==0){
eusureQueueTaskHandled(command);
}
}
//如果线程池不处于运行中或者无法放入任务队列,并且当前线程小于最大允许线程,则创建新线程
if(!addundermaxpoolsize(command)){
reject(command);
}
}
}
工作线程伪代码如下:
public void runnable(){
Runnable task=firsttask;
firsttask=null;
while(task!=null||task=workQueue.get()!=null){
runtask(task);
task=null;
}
finally{
workDone(this);
}
}
线程池的使用
创建线程池:new ThreadPoolExecutor(corepoolsize,maxpoolsize,keepalivetime,millseconds,runnabletaskqueue,hander);
参数说明
runnabletaskqueue,是一个用于存储任务的阻塞队列,通常 arryayblockingqueue linkedblockingqueue pritoryblockingqueue
hander:饱和策略:1 abortpolicy 丢弃 2 discardpolicy 不丢弃 3 callerrunspolicy 只有调用者线程来执行,discardoldestpolicy 丢弃队列里最近的一个任务,并执行当前任务
keepalivetime:线程池中的工作线程空闲后,可以保持存活的有效时间
timeunit:可保持存活时间的 有效单位 天 ,小时 分,秒等
向线程池中提交任务:execute 和submit
execute 用于提交无返回值的结果
submit用于提交有返回值的线程
通过submit方法提交的线程会返回一个future类型的对象,通过这个future类对象可以判断返回值时否成功。通过future。get方法获取返回值,get方法会阻塞当前线程,直到任务完成,并且get方法可以设置时间来实现异步调用返回
关闭线程池
关闭线程池游两种方法:shutdown shutdownNow方法关闭线程池
shutdown原理:逐个遍历工作线程,调用工作线程的interrupt方法,所以无法中断响应的线程可能无法终止。
shutdownnow原理:首先将线程池设置成stop状态,然后尝试终止所有正在执行或暂停任务的线程,并返回等待执行的任务列表。只要调用了两种方法中的任意一种,则isshutdown返回true,当所有任务已关闭,才表示线程池关闭成功则isterminaled返回true,shutdownnow方法可能任务不一定会执行完。通常使用shutdown来关闭
合理配置线程池
cpu密集型任务应配置尽可能小的线程。如配置cup+1个线程。由于io密集型任务并不一定是在一直执行任务。所以应配置尽可能多的线程,如配置2*cup个线程。如果是混合型的任务则可以拆分。拆分成一个cup密集型的任务和一个io密集型的任务,如果这两个任务执行时间相差不大则吞吐量高于单线程任务,如果相差太大则没必要进行分解。
Runtime.getRuntime.getAvaliableProcessors 获得cup数量
优先级不同的任务可使用优先级队列pritorityblockqueue来处理
建议使用有界队列,因为出现异常任务积压时可以执行拒绝策略,及时预警
线程池的监控
taskcount :线程池中需要执行的任务数量
completaskcount:线程池已经完成的线程数量
largestpoolsize:线程池中曾经创建过的最大的线程数量
poolsize 线程池中的线程数量
getactivecount:线程池中活动的线程树
可以通过继承线程你来自定义线程池的 beforeExecute afterExecute terminated 方法来对线程池进行监控
本文出自 “iter工作总结” 博客,请务必保留此出处http://5855156.blog.51cto.com/5845156/1965072
标签:java 线程池原理
原文地址:http://5855156.blog.51cto.com/5845156/1965072