ThreadPoolExecutor线程池的使用和总结

  1. 为什么要用线程池:
    1. 减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
    2. 假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 在线程中执行任务的时间,T3 销毁线程时间。如果:T1 + T3 远大于 T2,则可以采用线程池,以提高服务器性能。
  2. 线程池的四个基本组成部分
    1. 线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;
    2. 工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;
    3. 任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
    4. 任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。
  3. ThreadPoolExecutor的产生
    1. 先从源头开始,即顶级接口是Executor,但是它并不是一个线程池,他只是一个类似执行线程工具的接口,真正的实现线程池接口是ExecutorService,接着AbstractExecutorService继承了ExecutorService,最后再到ThreadPoolExecutor继承AbstractExecutorService。
    2. Executor和Executors的区别:
      1. Executor是一个框架工具,主要是执行线程的操作。
      2. Executors是一个实现类,他的底层实现是由ThreadPoolExecutor实现的,实现的例子会在ThreadPoolExecutor分类那里看到。
  4. ThreadPoolExecutor参数说明:
    • public ThreadPoolExecutor(int corePoolSize,
                                int maximumPoolSize,
                                long keepAliveTime,
                                TimeUnit unit,
                                BlockingQueue<Runnable> workQueue,
                                ThreadFactory threadFactory,
                                RejectedExecutionHandler handler) //后两个参数为可选参数

       

    • corePoolSize:表示核心线程的个数,也就是说允许开始的时候开到多少个线程

    • maximumPoolSize:表示最大的线程个数,这个线程池能最多支持多少个线程。
    • keepAliveTime:当线程空闲时,保持活跃的时间
    •  TimeUnit unit,:时间的计量单位,如分钟
    • BlockingQueue<Runnable> workQueue:队列,一共有三种策略:1,直接提交。工作队列的默认选项是 SynchronousQueue它将任务直接提交给线程而不保持它们。直接提交通常要求无界 maximumPoolSizes 以避免拒绝新提交的任务。2,无界队列。使用无界队列(例如,不具有预定义容量的 LinkedBlockingQueue)将导致在所有 corePoolSize 线程都忙时新任务在队列中等待。3,有界队列。当使用有限的 maximumPoolSizes 时,有界队列(如 ArrayBlockingQueue)有助于防止资源耗尽,但是可能较难调整和控制。
    • ThreadFactory threadFactory为创建线程的工厂,一般为Executors.defaultThreadFactory()使用默认的创建工厂
    • RejectedExecutionHandler handler为拒绝策略,1:CallerRunsPolicy:线程调用运行该任务的 execute 本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。2:AbortPolicy:处理程序遭到拒绝将抛出运行时RejectedExecutionException。3:DiscardPolicy:不能执行的任务将被删除。4:DiscardOldestPolicy:如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)
  5. ThreadPoolExecutor分类
    1. ExecutorService newFixedThreadPool(int nThreads):固定大小线程池。可以看到,corePoolSize和maximumPoolSize的大小是一样的,keepAliveTime和unit的设值表示什么?-就是该实现不想keep alive!最后的BlockingQueue选择了LinkedBlockingQueue,该queue有一个特点,他是无界的。
      1. public static ExecutorService newFixedThreadPool(int nThreads) {  
                return new ThreadPoolExecutor(nThreads, nThreads,  
                                              0L, TimeUnit.MILLISECONDS,  
                                              new LinkedBlockingQueue<Runnable>());  
            }  

         

    2. ExecutorService newSingleThreadExecutor():单线程。可以看到,与fixedThreadPool很像,只是fixedThreadPool中的入参直接为1

      1. public static ExecutorService newSingleThreadExecutor() {  
                return new FinalizableDelegatedExecutorService  
                    (new ThreadPoolExecutor(1, 1,  
                                            0L, TimeUnit.MILLISECONDS,  
                                            new LinkedBlockingQueue<Runnable>()));  
            }  

         

    3. ExecutorService newCachedThreadPool():无界线程池,可以进行自动线程回收。

      1. public static ExecutorService newCachedThreadPool() {  
                return new ThreadPoolExecutor(0, Integer.MAX_VALUE,  
                                              60L, TimeUnit.SECONDS,  
                                              new SynchronousQueue<Runnable>());  
            }  
         

         

  6. ThreadPoolExecutor实操例子
    1. 封装工具类
      1. public class ThreadPoolManager {
        
        	protected static Logger logger = LoggerFactory.getLogger(ThreadPoolManager.class);
        
        	// 通过ThreadPoolExecutor的代理类来对线程池的管理
        	private static ThreadPoolProxy mThreadPoolProxy;
        
        	// 单例对象
        	public static ThreadPoolProxy getThreadPollProxy() {
        		synchronized (ThreadPoolProxy.class) {
        			if (mThreadPoolProxy == null) {
        				mThreadPoolProxy = new ThreadPoolProxy(50, 300, 30);
        			}
        		}
        		return mThreadPoolProxy;
        	}
        	
        	public static ThreadPoolProxy getThreadPollProxy(int corePoolSize, int maximumPoolSize) {
        		synchronized (ThreadPoolProxy.class) {
        			if (mThreadPoolProxy == null) {
        				mThreadPoolProxy = new ThreadPoolProxy(corePoolSize, maximumPoolSize, 30);
        			}
        		}
        		return mThreadPoolProxy;
        	}
        
        	// 通过ThreadPoolExecutor的代理类来对线程池的管理
        	public static class ThreadPoolProxy {
        		private ThreadPoolExecutor poolExecutor;// 线程池执行者 ,java内部通过该api实现对线程池管理
        		private int corePoolSize;
        		private int maximumPoolSize;
        		private long keepAliveTime;
        
        		public ThreadPoolProxy(int corePoolSize, int maximumPoolSize, long keepAliveTime) {
        			this.corePoolSize = corePoolSize;
        			this.maximumPoolSize = maximumPoolSize;
        			this.keepAliveTime = keepAliveTime;
        		}
        
        		// 对外提供一个执行任务的方法
        		public void execute(Runnable r) {
        			if (poolExecutor == null || poolExecutor.isShutdown()) {
        				poolExecutor = new ThreadPoolExecutor(
        						// 核心线程数量
        						corePoolSize,
        						// 最大线程数量
        						maximumPoolSize,
        						// 当线程空闲时,保持活跃的时间
        						keepAliveTime,
        						// 时间单元:分钟
        						TimeUnit.MINUTES,
        						// 线程任务队列,吞吐性能较好,指定初始大小
        						new LinkedBlockingQueue<Runnable>(300),
        						// 使用默认创建线程的工厂
        						Executors.defaultThreadFactory(),
        						// 使用默认拒绝策略
        						new MyAbortPolicy());
        			}
        			poolExecutor.execute(r);
        		}
        	}
        
        	public static class MyAbortPolicy implements RejectedExecutionHandler {
        
        		public MyAbortPolicy() {
        		}
        
        		public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        			logger.error("【队列溢出,拒绝策略】线程池管理的工具类,封装类:Task " + r.toString() + " rejected from " + e.toString(), e);
        		}
        	}
        }

         

    2. 实际调用
      1. public void processAutoMigration() {
        		MainTask mainTask = new MainTask("hello", "world");
        		ThreadPoolManager.getThreadPollProxy(100, 300).execute(mainTask);
        	}
        
        class MainTask implements Runnable {
        		private String a;
        		private String b;
        
        		public MainTask(String a, String b) {
        			this.a = a;
                    this.b = b;
        		}
        
        		@Override
        		public void run() {
        			System.out.println(a+","+b);
        		}
        	}

         

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值