线程基础–线程生命周期
线程池
jdk提供的线程池
jdk的concurrent包的Executors工具类里为我们提供了静态方法,来方便我们创建线程池。
1. Executors.newSingleThreadExecutor();
/**
* Creates an Executor that uses a single worker thread operating
* off an unbounded queue. (Note however that if this single
* thread terminates due to a failure during execution prior to
* shutdown, a new one will take its place if needed to execute
* subsequent tasks.) Tasks are guaranteed to execute
* sequentially, and no more than one task will be active at any
* given time. Unlike the otherwise equivalent
* {@code newFixedThreadPool(1)} the returned executor is
* guaranteed not to be reconfigurable to use additional threads.
*
* @return the newly created single-threaded Executor
*/
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
很简单,SingleThread就是单线程,这个静态方法为我们返回一个单线程线程池,注解中说明这是创建了一个带有无界等待队列的单线程线程池,
注意当这个线程因执行失败而终止后会有一个新线程继续执行剩下的任务
,这个线程池保证了任务按序进行。
下面看一下传入ThreadPoolExecutor的参数
new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>())
核心线程数和最大线程数都是1,线程空闲存活时间为0ms(无空闲线程,此参数无意义),用LinkedBlockingQueue来存放任务队列,从上面的注解中我们知道这是一个无界的等待队列(其实是有界的)。我们再看下LinkedBlockingQueue的构造函数
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}
public LinkedBlockingQueue(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
last = head = new Node<E>(null);
}
LinkedBlockingQueue的任务队列最大长度为Integer.MAX_VALUE
2. Executors.newFixedThreadPool(n);
/**
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue. At any point, at most
* {@code nThreads} threads will be active processing tasks.
* If additional tasks are submitted when all threads are active,
* they will wait in the queue until a thread is available.
* If any thread terminates due to a failure during execution
* prior to shutdown, a new one will take its place if needed to
* execute subsequent tasks. The threads in the pool will exist
* until it is explicitly {@link ExecutorService#shutdown shutdown}.
*
* @param nThreads the number of threads in the pool
* @return the newly created thread pool
* @throws IllegalArgumentException if {@code nThreads <= 0}
*/
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
注解中说明这个方法创建了一个工作在无界等待队列上,重复使用固定数目线程的线程池。可以形象地称之为定长线程池。同单例线程池一样,核心线程数和最大线程数相等,等待队列为LinkedBlockingQueue。其实当使用LinkedBlockingQueue作为等待队列时,最大线程数在大于核心线程数时无意义,因为非核心线程仅在核心线程都在工作&&等待队列满时,才会被创建,而LinkedBlockingQueue一般不会满,因为在那之前就已经StackOverflow了。
3. Executors.newCachedThreadPool();
/**
* Creates a thread pool that creates new threads as needed, but
* will reuse previously constructed threads when they are
* available. These pools will typically improve the performance
* of programs that execute many short-lived asynchronous tasks.
* Calls to {@code execute} will reuse previously constructed
* threads if available. If no existing thread is available, a new
* thread will be created and added to the pool. Threads that have
* not been used for sixty seconds are terminated and removed from
* the cache. Thus, a pool that remains idle for long enough will
* not consume any resources. Note that pools with similar
* properties but different details (for example, timeout parameters)
* may be created using {@link ThreadPoolExecutor} constructors.
*
* @return the newly created thread pool
*/
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
SynchronousQueue(默认非公平队列),内部初始化一个TransferQueue,由TransferQueue来处理任务。SynchronousQueue无队列长度概念,看看类上的注解:
A {@linkplain BlockingQueue blocking queue} in which each insert
* operation must wait for a corresponding remove operation by another
* thread, and vice versa. A synchronous queue does not have any
* internal capacity, not even a capacity of one.
翻译:一个synchronous队列没有任何内部容量,甚至连一个都没有。因为每个插入操作都必须等待一个对应的消费操作完成。即队列长度应为0.
生产者线程放入任务且需阻塞到任务被消费者线程处理,(消费者线程即线程池中的线程)。。该线程池最大线程数为Integer.MAX_VALUE,表示来一个任务则立刻分派线程处理,如果有空闲 线程,则由空闲线程处理,否则新建线程来处理。(SynchronousQueue内部transferer变量用volatile修饰,保证了对象信息在线程间的同步。具体参照SynchronousQueue源码)
4. Executors.newScheduledThreadPool(n);
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
DelayedWorkQueue是非公共类,必须被声明为BlockingQueue对象,但能存放RunnableScheduledFuture对象,通过RunnableScheduledFuture接口的实现类ScheduledFutureTask可创建周期执行的定时任务。DelayedWorkQueue初始容量为16,可扩容,最大容量为Integer.MAX_VALUE。
5. Executors.newWorkStealingPool(n);
这个方法虽然也在Executors中,但它不是由ThreadPoolExecutor创建,而是由新的线程池类ForkJoinPool来创建。
/**
* Creates a thread pool that maintains enough threads to support
* the given parallelism level, and may use multiple queues to
* reduce contention. The parallelism level corresponds to the
* maximum number of threads actively engaged in, or available to
* engage in, task processing. The actual number of threads may
* grow and shrink dynamically. A work-stealing pool makes no
* guarantees about the order in which submitted tasks are
* executed.
*
* @param parallelism the targeted parallelism level
* @return the newly created thread pool
* @throws IllegalArgumentException if {@code parallelism <= 0}
* @since 1.8
*/
public static ExecutorService newWorkStealingPool(int parallelism) {
return new ForkJoinPool
(parallelism,
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null, true);
}
WorkStealingPool是一个并发线程池,并发度可作为参数传入(默认为服务器的CPU数),该线程池中的任务可并发执行,适用于运算量大且耗时的任务,最后一个参数为true表示任务队列默认按FIFO方式处理,false则按FILO方式处理。