Java Concurrency 2: ThreadPool
来源:互联网 发布:mysql 默认值约束 编辑:程序博客网 时间:2024/06/14 01:43
基本概念
《设计模式之禅》将对象池作为一种新的设计模式来看待,在重复生成对象的操作影响性能的时候适合将对象池化,这样看线程池算是对象池模式的一个典型应用了,其他应用还有DBCP、C3P0等数据库连接池,实际开发中如果使用对象池,可以用common-pool工具包来辅助实现,方便快捷。
使用线程池的好处:
- 降低资源消耗
- 提高响应速度
- 提高线程的可管理性
工厂类Executors可以建立几种常用的线程池:
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); } public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue()); } public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue())); }
另外还有workStealingPool和scheduledThreadPool,其实都是调用了ThreadPoolExecutor类来新建线程池,下面分析下这个类。
ThreadPoolExecutor参数:
先看看jdk源码中对参数的说明:
/** * Creates a new {@code ThreadPoolExecutor} with the given initial * parameters. * * @param corePoolSize the number of threads to keep in the pool, even * if they are idle, unless {@code allowCoreThreadTimeOut} is set * @param maximumPoolSize the maximum number of threads to allow in the * pool * @param keepAliveTime when the number of threads is greater than * the core, this is the maximum time that excess idle threads * will wait for new tasks before terminating. * @param unit the time unit for the {@code keepAliveTime} argument * @param workQueue the queue to use for holding tasks before they are * executed. This queue will hold only the {@code Runnable} * tasks submitted by the {@code execute} method. * @param threadFactory the factory to use when the executor * creates a new thread * @param handler the handler to use when execution is blocked * because the thread bounds and queue capacities are reached * @throws IllegalArgumentException if one of the following holds:<br> * {@code corePoolSize < 0}<br> * {@code keepAliveTime < 0}<br> * {@code maximumPoolSize <= 0}<br> * {@code maximumPoolSize < corePoolSize} * @throws NullPointerException if {@code workQueue} * or {@code threadFactory} or {@code handler} is null */ 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; }
- corePoolSize—核心线程数
核心线程会一直存活,即使没有任务需要处理。当线程数小于核心线程数时,即使现有的线程空闲,线程池也会优先创建新线程来处理任务,而不是直接交给现有的线程处理。
核心线程在allowCoreThreadTimeout被设置为true时会超时退出,默认情况下不会退出。 - maximumPoolSize—最大线程数
当线程数大于或等于核心线程,且任务队列已满时,线程池会创建新的线程,直到线程数量达到maxPoolSize。如果线程数已等于maxPoolSize,且任务队列已满,则已超出线程池的处理能力,线程池会拒绝处理任务而抛出异常。 - workQueue—任务队列
保存等待执行的任务的阻塞队列,可以选择一下几种:- ArrayBlockingQueue
基于数组的有界阻塞队列,FIFO。 - LinkedBlockingQueue
基于链表的阻塞队列,FIFO;静态工厂方法Executors.newFixedThreadPool()即使用该队列。 - SynchronousQueue
不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入会一直处于阻塞状态,吞吐量通常会高于LinkedBlockingQueue。静态工厂方法Executors.newCachedThreadPool()即使用该队列。 - PriorityBlockingQueue
- ArrayBlockingQueue
- keepAliveTime
当线程空闲时间达到keepAliveTime,该线程会退出,直到线程数量等于corePoolSize。如果allowCoreThreadTimeout设置为true,则所有线程均会退出直到线程数量为0。 - allowCoreThreadTimeout
是否允许核心线程空闲退出,默认值为false。 - queueCapacity
任务队列容量。从maxPoolSize的描述上可以看出,任务队列的容量会影响到线程的变化,因此任务队列的长度也需要恰当的设置。
任务提交:
- submit()
需要返回信息,其内部还是调用的execute() - execute()
线程池按以下顺序执行任务:
- 当线程数小于核心线程数时,创建线程。
- 当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列。
- 当线程数大于等于核心线程数,且任务队列已满
- 若线程数小于最大线程数,创建线程
- 若线程数等于最大线程数,抛出异常,拒绝任务
参数设置
实际应用场景一般不会直接调用Executors直接这几种线程,而是根据响应需求和系统资源综合考虑,
IO密集型和CPU密集型
我们可以把任务分为计算密集型和IO密集型。
计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如计算圆周率、对视频进行高清解码等等。这种类型的任务越多,花在任务切换的时间就越多,导致CPU执行任务的时间减少。所以,要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数。
IO密集型,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度),涉及到网络、磁盘IO的任务都是IO密集型任务。对于IO密集型任务,任务越多,CPU效率越高,但也有一个限度。常见的大部分任务都是IO密集型任务,比如Web应用。
参考:
http://blog.csdn.net/miclung/article/details/7231553
http://www.cnblogs.com/jinzhiming/p/5120623.html
http://www.blogjava.net/bolo/archive/2015/01/20/422296.html
- Java Concurrency 2: ThreadPool
- 知识库--Concurrency+ThreadPool+Executors(79)
- Java ThreadPool
- java-threadpool
- java concurrency in pactice_Chapter 2
- java concurrency in practice - 2
- java concurrency
- java concurrency
- Java Concurrency
- Java Concurrency
- Java Concurrency
- Java Concurrency
- threadpool 2
- 【Notes】Effective Java 2nd -- Concurrency
- Effective Java, 2nd - Concurrency - Notes
- Java多线程之ThreadPool
- Java多线程之ThreadPool
- java线程池(ThreadPool)
- 可视化编程笔记
- 【转】TCP粘包问题解决方法之\n\r
- 1.3用高阶函数做抽象
- Android Studio中的APK分析器
- Virtualenv的使用
- Java Concurrency 2: ThreadPool
- 数据挖掘学习之决策树算法
- 简述编译与链接
- java jni编程之hello world
- linux常用命令
- JAVA集合
- js scrollTop
- pandas的应用案例
- Freemaker页面的注释