Java线程池深入理解

最近项目中进行告警模块性能优化,不少地方使用了线程池技术,整理总结如下。

package com.coshaho.threadpool;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 线程池学习
 * @author coshaho
 */
public class MyThreadPool
{
	/**
	 * 第一章  线程池初始化
	 */
	// 核心线程数量
	private int corePoolSize;
	// 最大线程数量
	private int maximumPoolSize;
	// 空闲线程存活时间
	private long keepAliveTime;
	// 空闲线程存活时间单位
	private TimeUnit unit;
	// 线程阻塞队列
	private BlockingQueue<Runnable> workQueue;
	/**
	 *  线程创建工厂,一般自定义,用于封装传入ThreadPool的Runnable任务
	 *  默认:Executors.defaultThreadFactory()
	 *  public interface ThreadFactory {
	 *      Thread newThread(Runnable r);
	 *  }
	 */
	private ThreadFactory threadFactory;
	// 线程拒绝机制
	private RejectedExecutionHandler handler;

	public void initThreadPoolExecutor()
	{
		ThreadPoolExecutor executor = new ThreadPoolExecutor(
				corePoolSize,
				maximumPoolSize,
				keepAliveTime,
				unit,
				workQueue,
				threadFactory,
				handler);
		// 设置线程池核心线程数
		executor.setCorePoolSize(corePoolSize);
		// 设置线程池最大线程数
		executor.setMaximumPoolSize(maximumPoolSize);
		// 初始化一个核心线程
		executor.prestartCoreThread();
		// 初始化所有核心线程
		executor.prestartAllCoreThreads();
		// 不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务
		executor.shutdown();
		// 立即终止线程池,尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务
		executor.shutdownNow();
	}

	/**
	 * 第二章  线程池任务处理机制
	 * 来了一个任务后的处理机制
	 * 1、 当线程池线程数量小于corePoolSize时,立即新建一个线程执行任务;
	 * 2、 当线程池线程数量等于corePoolSize,workQueue不满时,任务入workQueue队列,等待调度;
	 * 3、 当workQueue满,线程池线程数量小于maximumPoolSize时,新建线程执行任务;
	 * 4、 当线程池线程数量等于maximumPoolSize,workQueue满时,采用线程拒绝机制处理任务。
	 */

	/**
	 * 第三章  线程阻塞队列
     * workQueue的类型为BlockingQueue<Runnable>,通常可以取下面三种类型:
         * 1、ArrayBlockingQueue:基于数组的先进先出队列,此队列创建时必须指定大小;
         * 2、LinkedBlockingQueue:基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE;
         * 3、synchronousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。
	 */

	/**
	 * 第四章  线程拒绝机制
	 */
	public void rejectedExecutionHandlerLearn()
	{
		// 丢弃任务并抛出RejectedExecutionException异常
		handler = new ThreadPoolExecutor.AbortPolicy();
		// 也是丢弃任务,但是不抛出异常
		handler = new ThreadPoolExecutor.DiscardPolicy();
		// 丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
		handler = new ThreadPoolExecutor.DiscardOldestPolicy();
		// 由调用线程处理该任务
		handler = new ThreadPoolExecutor.CallerRunsPolicy();
	}

	/**
	 * 第五章  JDK默认线程池
	 */

	public void jdkThreadPool()
	{
		//创建一个缓冲池,缓冲池容量大小为Integer.MAX_VALUE
		Executors.newCachedThreadPool();
		//创建容量为1的缓冲池
		Executors.newSingleThreadExecutor();
		//创建固定容量大小的缓冲池
		Executors.newFixedThreadPool(5);
	}
	/**
	public static ExecutorService newFixedThreadPool(int nThreads) {
    	return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
	}
	public static ExecutorService newSingleThreadExecutor() {
    	return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
	}
	public static ExecutorService newCachedThreadPool() {
    	return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
	}
	*/

	/**
	 * 第六章  线程池大小设置
	 * 1、 如果是CPU密集型任务,就需要尽量压榨CPU,参考值可以设为 NCPU+1;
         * 2、 如果是IO密集型任务,参考值可以设置为2*NCPU。
	 */

	/**
	 * 第七章  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)
     */
}
时间: 2024-10-10 18:27:55

Java线程池深入理解的相关文章

Java并发编程与技术内幕:线程池深入理解

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要: 本文主要讲了Java当中的线程池的使用方法.注意事项及其实现源码实现原理,并辅以实例加以说明,对加深Java线程池的理解有很大的帮助. 首先,讲讲什么是线程池?照笔者的简单理解,其实就是一组线程实时处理休眠状态,等待唤醒执行.那么为什么要有线程池这个东西呢?可以从以下几个方面来考虑:其一.减少在创建和销毁线程上所花的时间以及系统资源的开销 .其二.2将当前任务与主线程隔离,能实现和主

线程池深入理解

一 使用线程池的好处 合理利用线程池能够带来三个好处.第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗.第二:提高响应速度.当任务到达时,任务可以不需要的等到线程创建就能立即执行.第三:提高线程的可管理性.线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控. 二 在何种情况下使用线程池 要想合理的配置线程池,就必须首先分析任务特性,可以从以下几个角度来进行分析: 1.                   任

死磕 java线程系列之线程池深入解析——未来任务执行流程

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 注:线程池源码部分如无特殊说明均指ThreadPoolExecutor类. 简介 前面我们一起学习了线程池中普通任务的执行流程,但其实线程池中还有一种任务,叫作未来任务(future task),使用它您可以获取任务执行的结果,它是怎么实现的呢? 建议学习本章前先去看看彤哥之前写的<死磕 java线程系列之自己动手写一个线程池(续)>,有助于理解本章的内容,且那边的代码比较短小,学起来相对容易一些. 问题

死磕 java线程系列之线程池深入解析——体系结构

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 简介 Java的线程池是块硬骨头,对线程池的源码做深入研究不仅能提高对Java整个并发编程的理解,也能提高自己在面试中的表现,增加被录取的可能性. 本系列将分成很多个章节,本章作为线程池的第一章将对整个线程池体系做一个总览. 体系结构 上图列举了线程池中非常重要的接口和类: (1)Executor,线程池顶级接口: (2)ExecutorService,线程池次级接口,对Executor做了一些扩展,增加一

死磕 java线程系列之线程池深入解析——生命周期

摘自:https://www.cnblogs.com/tong-yuan/p/11748887.html (手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 注:线程池源码部分如无特殊说明均指ThreadPoolExecutor类. 简介 上一章我们一起重温了下线程的生命周期(六种状态还记得不?),但是你知不知道其实线程池也是有生命周期的呢?! 问题 (1)线程池的状态有哪些? (2)各种状态下对于任务队列中的任务有何影响? 先上源码 其实,在我们讲线程池体

死磕 java线程系列之线程池深入解析——构造方法

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 简介 ThreadPoolExecutor的构造方法是创建线程池的入口,虽然比较简单,但是信息量很大,由此也能引发一系列的问题,同样地,这也是面试中经常被问到的问题,下面彤哥只是列举了一部分关于ThreadPoolExecutor构造方法的问题,如果你都能回答上来,则可以不用看下面的分析了. 问题 (1)ThreadPoolExecutor有几个构造方法? (2)ThreadPoolExecutor最长的构

死磕 java线程系列之线程池深入解析——定时任务执行流程

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 注:本文基于ScheduledThreadPoolExecutor定时线程池类. 简介 前面我们一起学习了普通任务.未来任务的执行流程,今天我们再来学习一种新的任务--定时任务. 定时任务是我们经常会用到的一种任务,它表示在未来某个时刻执行,或者未来按照某种规则重复执行的任务. 问题 (1)如何保证任务是在未来某个时刻才被执行? (2)如何保证任务按照某种规则重复执行? 来个栗子 创建一个定时线程池,用它来

ThreadPoolExecutor线程池深入解读(一)----原理+应用

本文档,适合于对多线程有一定基础的开发人员.对多线程的一些基础性的解读,请参考<java并发编程>的前5章. 多线程编程,在软件开发中占有十分重要的地位.本人对线程同步的本质的理解是:把对一个或者多个的共享状态的复合操作转变为原子性的操作,同时保证共享状态在内存中的可见性. 1.多线程并发时,会存在竞态条件.常见的竞态条件包括先检查后执行机制的竞争和原子性操作竞争,比如同时对一个整数++操作,这个操作可以分割为三个步骤:读取.加法操作与写入(生效).解决先检查后执行机制的竞态条件的有效手段是采

java线程池ThreadPoolExecutor理解

Java通过Executors提供四种线程池,分别为:newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程.newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待.newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行.newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有