public class ThreadPoolExecutor extends AbstractExecutorService
ThreadPoolExecutor 继承了ExecutorService接口的抽象实现类AbstractExecutorService,提供了四个构造方法供编码者使用:
前面三个方法都是给定默认参数替代没有传递的参数然后this调用最后一个满参数的构造函数,源代码如下:
- public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
- this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler);
- }
上面这个构造方法就提供了一个默认的线程工厂和一个默认的拒绝handler。
通过ThreadPoolExecutor的构造方法得到的线程池使用方法和Executors.newFixedThreadPool()方法得到的线程池使用方式是一样的,你可以以ExecutorService来接收它,通过ExecutorService的sumbit()方法提交你要管理的线程。
这里再解读一下线程工厂和拒绝handler的源码,首先从handler开始:
这里的RejectedExecutionHandler是java的concurrent包下的一个接口,java对其提供了四种实现:
它的主要负责的是在线程池内的线程都处于工作状态时,有新的任务提交进来的处理工作。
1.AbortPolicy 从名字上面就可以看到,Abort-舍弃、终止,直接设置提交进来的任务,但是它在舍弃前还抛出一个异常,这也是未提交策略参数时,使用的默认策略:
- public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
- throw new RejectedExecutionException();
- }
- /**
- * The default rejected execution handler
- */
- private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();
2.CallerRunsPolicy 这个策略是在线程池满负荷时,将会一直重试将此线程任务添加到线程池中。注意,如果线程池采用此种策略,可能会导致占用cpu的过多的时间进行重新添加操作,导致真正在线程池中需要执行的线程分不到cpu的时间片。
- /**
- * Executes task r in the caller's thread, unless the executor
- * has been shut down, in which case the task is discarded.
- * @param r the runnable task requested to be executed
- * @param e the executor attempting to execute this task
- */
- public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
- if (!e.isShutdown()) {
- r.run();
- }
- }
3.DiscardPolicy 这个策略直接贴源码吧
- /**
- * Does nothing, which has the effect of discarding task r.
- * @param r the runnable task requested to be executed
- * @param e the executor attempting to execute this task
- */
- public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
- }
看见了吗,注释里面大大的Does nothing。人家啥也不干,方法体内就是空的。你任务没了他都不给你提示。
4.DiscardOldestPolicy 这个策略和上面的类似,不过它是将线程池队列最老一个任务枪毙,然后把这个任务拉进来
- /**
- * Obtains and ignores the next task that the executor
- * would otherwise execute, if one is immediately available,
- * and then retries execution of task r, unless the executor
- * is shut down, in which case task r is instead discarded.
- * @param r the runnable task requested to be executed
- * @param e the executor attempting to execute this task
- */
- public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
- if (!e.isShutdown()) {
- e.getQueue().poll();
- e.execute(r);
- }
- }
以上为Handle java提供的实现类的解答,如果这四种不满足使用需求,希望处理方法更加复杂一点,比如将多出来的任务放到某个地方,等这边线程池过了高峰再去处理的话,可以自己实现RejectedExecutionHandler接口,在rejectedExecution()方法体中写入你需要的逻辑。
接下来看看线程工厂的源码:
ThreadFactory也是concurrent包下的接口,贴下源码和注释:
- /**
- * An object that creates new threads on demand. Using thread factories
- * removes hardwiring of calls to {@link Thread#Thread(Runnable) new Thread},
- * enabling applications to use special thread subclasses, priorities, etc.
- *
- * <p>
- * The simplest implementation of this interface is just:
- * <pre>
- * class SimpleThreadFactory implements ThreadFactory {
- * public Thread newThread(Runnable r) {
- * return new Thread(r);
- * }
- * }
- * </pre>
- *
- * The {@link Executors#defaultThreadFactory} method provides a more
- * useful simple implementation, that sets the created thread context
- * to known values before returning it.
- * @since 1.5
- * @author Doug Lea
- */
- public interface ThreadFactory {
- /**
- * Constructs a new {@code Thread}. Implementations may also initialize
- * priority, name, daemon status, {@code ThreadGroup}, etc.
- *
- * @param r a runnable to be executed by new thread instance
- * @return constructed thread, or {@code null} if the request to
- * create a thread is rejected
- */
- Thread newThread(Runnable r);
- }
可以看到,接口内只有一个方法,newThread(),从名字和注释都可以知道,主要功能就是创建一个新的线程。
ThreadPoolExecutor中的默认线程工厂是类Executors的一个内部类
- /**
- * The default thread factory
- */
- 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() {
- public final native void wait(long timeout) throws InterruptedException;
SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-"; } public Thread newThread(Runnable r) { Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); if (t.isDaemon()) t.setDaemon(false); if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY); return t; } }上面默认的线程工厂也就是在创建线程时,设置了线程的组,线程名和优先级。我们也可以自己去实现ThreadFactory类,创建线程。下次有机会补上代码及测试。