最近才写完毕业论文的初稿,现在终于有些时间来写一下博客了。
那就来看看线程池的知识点吧。
这篇文章只讲一下常用的一些线程池的构造方法吧。其他方面后面再写写(突然发现以前的博客写的都不太好,以后格式会注意写好一些)。
先来看看我们常用的:
看一下我们平常可能会用得比较多的Executors类中的四个静态方法:
public static ExecutorService newCachedThreadPool()
public static ExecutorService newFixedThreadPool(int nThreads)
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
public static ExecutorService newSingleThreadExecutor()
当然,他们都还有另外一个重载的方法,后面再说好伐?
如果你稍微看了一下它们的源码,你会发现到最后他们都会导向下面这个方法中(这个方法在java.util.concurrent.ThreadPoolExecutor中)
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue 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.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
然后我们来看一下他的主要的属性吧,其实Doug大神已经在注释上写得清楚了,那我就翻译一下吹吹水好了:
corePoolSize:核心线程数(后面再讲讲这个)
maximumPoolSize:允许创建的最大线程数
keepAliveTime:这个看一下单词也能猜出它的主要作用了吧?当线程池的线程数大于核心线程数的时候,线程空闲时间超过这个时间后还没有任务给它做的话就会关闭。小于等于核心线程数的时候不会被关闭,但是可以通过public void allowCoreThreadTimeOut(true)来设置使其可以被关闭。
TimeUnit unit:keepAliveTime的时间单位(作转换用)
this.keepAliveTime = unit.toNanos(keepAliveTime);
BlockingQueue
ThreadFactory threadFactory:生成线程的工厂,另一个重载的方法就是带有这个参数的。
RejectedExecutionHandler handler:当线程池满了,但还有新任务提交的时候,就会采用这个策略来进行处理。ThreadPoolExecutor中已经定义好四个实现类了:
public static class AbortPolicy implements RejectedExecutionHandler;
直接抛出 RejectedExecutionException 异常,这个是默认的处理策略。
public static class CallerRunsPolicy implements RejectedExecutionHandler;
如果线程池没有被关闭,就交由提交任务的线程来执行。
public static class DiscardOldestPolicy implements RejectedExecutionHandler
这个策略就是讲等待队列头的任务给扔掉,然后将这个新任务提交到等待队列中。
public static class DiscardPolicy implements RejectedExecutionHandler
不鸟你,不做任何处理。
好了,讲完主要的参数。就来讲一下主要的吧:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue
}
上面的你都看完了就知道这里讲什么了。核心线程数为 0,最大线程数为 Integer.MAX_VALUE,keepAliveTime 为 60 秒,任务队列采用 SynchronousQueue。
这种线程池对于任务可以快速地完成的时候会有比较好的性能。如果线程空闲了 60 秒都没有任务,那么将关闭此线程并从线程池中移除。随着所有的线程都会被关闭,整个线程池不会占用任何的系统资源,所以如果线程池空闲了很长时间也不会有问题。
SynchronousQueue 是一个比较特殊的 BlockingQueue,它不储存任何元素,有一个虚拟队列,不管读操作还是写操作,如果当前队列中存储的是与当前操作相同模式的线程,那么当前操作也进入队列中等待;如果是相反模式,则配对成功,从当前队列中取队头节点。
这篇文章暂时不是太深入的聊,或许我会在后续文章中补上聊一下。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L , TimeUnit. MILLISECONDS ,核心线程数为 nThreads(参数指定的),最大线程数为 nThreads,keepAliveTime 为 0 秒,任务队列采用 LinkedBlockingQueue。
LinkedBlockingQueue是基于单向链表实现的阻塞队列。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue
}
核心线程数为 1,最大线程数为 1,keepAliveTime 为 0 秒,任务队列采用 LinkedBlockingQueue。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
核心线程数为 corePoolSize(参数指定),最大线程数为 Integer.MAX_VALUE,keepAliveTime 为 0 秒,任务队列采用 DelayedWorkQueue。
好吧,这篇就先到这里吧。具体的实现流程我后面的博客再详细写一下吧。。。欢迎大佬们点(sao)评(rao)。