线程池实现类ThreadPoolExecutor
ExecutorService接口扩展了Executor接口,添加了一些用于生命周期的管理方法,ThreadPoolExecutor继承了AbstractExecutorService,而AbstractExecutorService又实现了ExecutorService接口。
ThreadPoolExecutor的通用构造函数为:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
- corePoolSize(线程池的基本大小):当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能 够执行新任务也会创建线程,等到需要执行的任务数大于线程池基本大小时就不再创建。如果调用了线程池的prestartAllCoreThreads方 法,线程池会提前创建并启动所有基本线程。
- runnableTaskQueue(任务队列):用于保存等待执行的任务的阻塞队列。 可以选择以下几个阻塞队列。
- ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序。
- LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列。
- SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直 处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool使用 了这个队列。
- PriorityBlockingQueue:一个具有优先级的无限阻塞队列。
- maximumPoolSize(线程池最大大小):线程池允许创建的最大线程数。如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务。值得注意的是如果使用了无界的任务队列这个参数就没什么效果。
- ThreadFactory:用于设置创建线程的工厂,可以通过线程工厂给每个创建出来的线程设置更有意义的名字。
- RejectedExecutionHandler(饱和策略):当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务。这个策略默认情况下是AbortPolicy,表示无法处理新任务时抛出异常。以下是JDK1.5提供的四种策略。
- AbortPolicy:直接抛出异常。
- CallerRunsPolicy:只用调用者所在线程来运行任务。
- DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。
- DiscardPolicy:不处理,丢弃掉。
- 当然也可以根据应用场景需要来实现RejectedExecutionHandler接口自定义策略。如记录日志或持久化不能处理的任务。
- keepAliveTime(线程活动保持时间):线程池的工作线程空闲后,保持存活的时间。所以如果任务很多,并且每个任务执行的时间比较短,可以调大这个时间,提高线程的利用率。
- TimeUnit(线程活动保持时间的单位):可选的单位有天(DAYS),小时(HOURS),分钟(MINUTES),毫秒(MILLISECONDS),微秒(MICROSECONDS, 千分之一毫秒)和毫微秒(NANOSECONDS, 千分之一微秒)。
线程池的创建
在Executors类里面提供了一些静态工厂,生成一些常用的线程池,Executors返回值的类型是ExecutorService,其内都是通过new ThreadPoolExecutor来实现的,而ExecutorService为ThreadPoolExecutor的接口,如Executors中的newFixedThreadPool方法:
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
Executors提供了下面几种创建线程的方法:
- newSingleThreadExecutor:创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
- newFixedThreadPool:创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
- newCachedThreadPool:创建一个可缓存的线程池。如果线程池的大小超过了处理任务 所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小 做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
- newScheduledThreadPool:创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求,相当于Timer。
- newSingleThreadScheduledExecutor:创建一个单线程的线程池。此线程池支持定时以及周期性执行任务的需求。
向线程池提交任务
Executor接口提供了void execute(Runnable command)方法向线程池提交任务,execute方法没有返回值,也无法判断任务是否被线程池执行成功。
ExecutorService接口添加了下面方法来提交线程任务:
<T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task);
它们的区别在于Runnable在执行完毕后没有结果,Callable执行完毕后有一个结果。这在多个线程中传递状态和结果是非常有用的。另外他 们的相同点在于都返回一个Future对象。Future对象可以阻塞线程直到运行完毕(获取结果,如果有的话),也可以取消任务执行,当然也能够检测任 务是否被取消或者是否执行完毕。在没有Future之前我们检测一个线程是否执行完毕通常使用Thread.join()或者用一个死循环加状态位来描述线程执行完毕。现在有了更好的方法能够阻塞线程,检测任务执行完毕甚至取消执行中或者未开始执行的任务。
相关推荐
主要给大家介绍了关于java线程池使用后到底要不要关闭的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
Java线程池使用说明Java线程池使用说明Java线程池使用说明
C# 线程池使用示例,vs2013 + 控制台窗口 简单实现。
c#线程池技术的demo,代码简单易学,对理解线程池有帮助。
线程池使用的几个demo
线程池使用基本框架,快速掌握线程池技术
ThreadPoolExecutor的使用和Android常见的4种线程池使用介绍
线程池使用实例,一个简单的使用线程池的例子
VB线程池使用
Linux线程池使用.docx
以下示例显示如何使用线程池。首先创建 ManualResetEvent 对象,此对象使程序能够知道线程池何时运行完所有的工作项。接着,尝试向线程池添加一个线程。如果添加成功,则添加其余的线程(本例中为 4 个)。然后...
本Demo演示了不同线程池运行的效果图,如果对多线程学习感兴趣,可以下载
linux线程池使用(动态调整).rar
多线程线程池使用 (C#3.5) 高效
java线程池使用说明[借鉴].pdf
1.线程池管理器(ThreadPoolManager):用于创建并管理线程池 2.工作线程(WorkThread): 线程池中线程 3.任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行。 4.任务队列:用于存放没有处理的...
建立TCP、UDP单播、组播 创建服务器端与客户端,服务器端使用select机制接收客户端的请求,并交给线程池处理
简单演示了如何使用线程池,可以再源代码的基础上进行修改进行更高级的操作,适合用于学习
Qt中的QThreadPool线程池的使用例子,包含QRunnable类的使用,代码仅供参考