
上面继续: Java线程池的原理研究 p>
ThreadPoolExecutor,线程池类,继承自AbstractExecutorService
public class ThreadPoolExecutor extends AbstractExecutorService
ThreadPoolExecutor提供了四种构造方法(这里仅介绍一种):
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
有必要解释每个参数:
为了便于在大量上下文中使用,此类提供了许多可调整的参数和扩展挂钩. jdk文档建议在正常情况下,使用执行程序提供的工厂方法配置,即提供良好的线程池. 如果要手动配置,则需要遵循以下规则:

ThreadPoolExecutor将根据corePoolSize和maximumPoolSize设置的边界自动调整池大小. 在执行方法(java.lang.Runnable)中提交新任务时:
1. 正在运行的线程小于corePoolSize,然后即使其他辅助线程都处于空闲状态,也要创建一个新线程来处理请求.
2: 运行比corePoolSize多且小于maximumPoolSize的线程,然后将任务放入队列,空闲线程将从队列中取出任务,并且仅在队列已满时创建新线程.
3: 如果设置的corePoolSize和maximumPoolSize相同,则会创建固定大小的线程池.
4: 如果将maximumPoolSize设置为基本的无界值(例如Integer.MAX_VALUE),则允许该池适应任何数量的并发任务.
请注意以下两点:
在大多数情况下,仅根据构造函数设置核心和最大池大小,但是您也可以使用setCorePoolSize(int)和setMaximumPoolSize(int)进行动态更改.

当池中的线程数大于corePoolSize时,多余的线程将长时间等待keepAliveTime,如果没有处理请求,则销毁它们自己.
使用ThreadFactory创建新线程. 除非另有说明,否则Executors.defaultThreadFactory()用于在同一ThreadGroup中创建线程,并且这些线程具有相同的NORM_PRIORITY优先级和非守护程序状态. 通过提供不同的ThreadFactory,可以更改线程名称,线程组,优先级,守护程序状态等. 如果从newThread返回null时ThreadFactory无法创建线程,则执行程序将继续运行,但无法执行任何任务.
ThreadFactory是线程工厂,它是一个接口:
public interface ThreadFactory {
Thread newThread(Runnable r);
}
ThreadPoolExecutor中的threadFactory由Executors工具类提供:
public static ThreadFactory defaultThreadFactory() {
return new DefaultThreadFactory();
}
static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = "pool-" +
poolNumber.getAndIncrement() +
"-thread-";
}
public Thread newThread(Runnable r) {
////创建的线程以“pool-N-thread-M”命名,N是该工厂的序号,M是线程号
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
//设为非后台线程
if (t.isDaemon())
t.setDaemon(false);
//优先级为normal
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}

DefaultThreadFactory是静态内部类
如前所述,当线程池中运行的线程等于或大于corePoolSize时,Executor总是更喜欢将请求添加到队列中而不添加新线程. 有三种将任务添加到队列的策略(有关详细信息,请参见jdk文档).
在两种情况下,新提交的任务将被拒绝:
执行器关闭时
执行器使用有限的边界来获得最大的线程和工作队列容量,并且已经饱和
对于被拒绝的任务,execute方法将调用其RejectedExecutionHandler的RejectedExecutionHandler.rejectedExecution(java.lang.Runnable,java.util.concurrent.ThreadPoolExecutor)方法. 以下提供了四种预定义的处理程序策略:
在默认的ThreadPoolExecutor.AbortPolicy中,被拒绝的处理程序将抛出运行时RejectedExecutionException.

在ThreadPoolExecutor.CallerRunsPolicy中,线程调用自身执行运行任务. 该策略提供了一种简单的反馈控制机制,可以降低新任务的提交速度.
在ThreadPoolExecutor.DiscardPolicy中java线程池执行原理,将删除无法执行的任务.
在ThreadPoolExecutor.DiscardOldestPolicy中java线程池执行原理,如果执行器尚未关闭,则将删除工作队列开头的任务,并将重试执行器(如果再次失败,请重复此过程).
也可以定义和使用其他种类的RejectedExecutionHandler类,但这需要格外小心,尤其是当该策略仅用于特定容量或排队策略时.
此类提供了两个受保护和可重写的钩子方法:
protected void beforeExecute(Thread t, Runnable r) { }
protected void afterExecute(Runnable r, Throwable t) { }
在每个任务之前和之后调用这两个方法. 它们可以用来操纵执行环境. 请注意,这里是每个任务,每次运行新任务时都会执行. 例如,重新初始化ThreadLocal,收集统计信息或添加日志条目. 此外,还可以重写终止方法(),以执行执行程序完全终止后需要执行的所有特殊处理.
如果钩子或回调方法引发异常,则内部辅助线程将依次失败并突然终止.
jdk文档提供了可以暂停和恢复的线程池的示例:
class PausableThreadPoolExecutor extends ThreadPoolExecutor {
private boolean isPaused;
private ReentrantLock pauseLock = new ReentrantLock();
private Condition unpaused = pauseLock.newCondition();
public PausableThreadPoolExecutor(...) { super(...); }
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
pauseLock.lock();
try {
while (isPaused) unpaused.await();
} catch(InterruptedException ie) {
t.interrupt();
} finally {
pauseLock.unlock();
}
}
public void pause() {
pauseLock.lock();
try {
isPaused = true;
} finally {
pauseLock.unlock();
}
}
public void resume() {
pauseLock.lock();
try {
isPaused = false;
unpaused.signalAll();
} finally {
pauseLock.unlock();
}
}
}
java线程池的原理学习(三)
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/ruanjian/article-204656-1.html
@CYAdol小米电源正品没问题
唱的太好了
就是阻滞中国的发展