线程池机制的理解


一、线程池的作用
线程池是预先创建线程的一种技术,线程池在还没有任务到来之前,创建一定数量的线程,放入到空闲队列中,然后对这些资源进行复用,每个工作线程都可以被重复利用,可执行多个任务。减少频繁的创建和销毁消耗资源,耗时间因为有的线程执行的时间比创建和销毁一个线程的时间还短那么线程池的作用就体现出来了.

二、涉及到线程池的类
* Executor:Java里面线程池的顶级接口。
* ExecutorService:真正的线程池接口。
* ScheduledExecutorService:能和Timer/TimerTask类似,解决那些需要任务重复执行的问题。
* ThreadPoolExecutor(重点):ExecutorService的默认实现。
* ScheduledThreadPoolExecutor:继承ThreadPoolExecutor的ScheduledExecutorService接口实现,周期性任务调度的类实现。
* Executors:可以一行代码创建一些常见的线程池。
三、Executors介绍
Executors是jdk1.5之后的一个新类,提供了一些静态方法,帮助我们方便的生成一些常用的线程池,ThreadPoolExecutor是Executors类的底层实现。
1.newSingleThreadExecutor
创建一个单线程的线程池,这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
2.newFixedThreadPool
创建固定大小的线程池,每次提交一个任务就会创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦到达最大值就会保持不变,如果某个线程因执行异常而结束,那么线程池会补充一个新的线程放入到池中。
3.newCachedThreadPool
创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数量增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池的大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
4.创建一个大小无线的线程池。该线程池支持定时以及周期性执行任务的需求。
四、线程池的创建
1.创建5个数量的线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);
2.线程池的调用
executorService.submit(线程类);
3.线程池的释放
executorService.shutdown();
4.封装线程池
public class ThreadPoolProxy {

    ThreadPoolExecutor mExecutor;

    int  mCorePoolSize;
    int  mMaximumPoolSize;
    long mKeepAliveTime;

    public ThreadPoolProxy(int corePoolSize, int maximumPoolSize, long keepAliveTime) {
        mCorePoolSize = corePoolSize;
        mMaximumPoolSize = maximumPoolSize;
        mKeepAliveTime = keepAliveTime;
    }

    //初始化
    private void initTheadPoolExecutor() {
        //如果等于 null  或者已经被关闭了 或者任务执行完成立马要关闭了
        if (mExecutor == null || mExecutor.isShutdown() || mExecutor.isTerminated()) {
            //单利的模式 初始化
            synchronized (ThreadPoolProxy.class) {
                //外部决定通过构造函数初始化
                int corePoolSize = mCorePoolSize;
                int maximumPoolSize = mMaximumPoolSize;
                long keepAliveTime = mKeepAliveTime;

                TimeUnit unit = TimeUnit.MILLISECONDS; // 单位毫秒
                BlockingQueue<Runnable> workQueue = new LinkedBlockingDeque<>();  // 队列
                ThreadFactory threadFactory = Executors.defaultThreadFactory(); //工厂
                RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy(); //处理方式:不做处理

                if (mExecutor == null || mExecutor.isShutdown() || mExecutor.isTerminated()) {
                    //初始化
                    mExecutor = new ThreadPoolExecutor(
                            corePoolSize, //核心线程数
                            maximumPoolSize, //最大线程池数
                            keepAliveTime, //保持时间
                            unit, //保持时间单位
                            workQueue, //任务队列
                            threadFactory,//线程工厂
                            handler); //异常捕获器
                }
            }
        }
    }

    /**
     * 1.提交任务和执行任务的区别
     *      是否有返回值,提交任务有返回值
     * 2.Future<?>是什么?
     *      1.得到任务执行之后的结果
     *      2.包含了一个get方法和cancle
     *      3.其中get方法,是一个阻塞的方法,会阻塞等待任务执行完成之后的结果,还可以try catch到任务执行过程中抛出的异常
     */
    

    /**
     * 提交任务
     */
    public Future<?> submit(Runnable task) {
        initTheadPoolExecutor();
        return mExecutor.submit(task);
    }

    /**
     * 执行任务
     */
    public void execute(Runnable task) {
        initTheadPoolExecutor();
        mExecutor.execute(task);
    }

    /**
     * 移除任务
     */
    public void remove(Runnable task) {
        initTheadPoolExecutor();
        mExecutor.remove(task);
    }
}
5.线程池的代理
public class ThreadPoolProxyFactory {

    static ThreadPoolProxy mNormalThreadPoolProxy;
    static ThreadPoolProxy mDownLoadThreadPoolProxy;

    public static ThreadPoolProxy createNormalThreadPoolProxy() {
        if (mNormalThreadPoolProxy == null) {
            synchronized (ThreadPoolProxyFactory.class) {
                if (mNormalThreadPoolProxy == null) {

                    mNormalThreadPoolProxy = new ThreadPoolProxy(5, 5, 3000);
                }
            }
        }
        return mNormalThreadPoolProxy;
    }
}
6.调用执行和移除任务
ThreadPoolProxyFactory.createDownLoadThreadPoolProxy().execute(线程类);
ThreadPoolProxyFactory.createDownLoadThreadPoolProxy().remove(线程类);


四、线程池的机制
corePoolSize: 核心线程数,能够同时执行的任务数量
maximumPoolSize:除去缓冲队列中等待的任务,最大能容纳的任务数(其实是包括了核心线程池数量)
keepAliveTime:超出workQueue的等待任务的存活时间,就是指maximumPoolSize里面的等待任务的存活时间
unit:时间单位
workQueue:阻塞等待线程的队列,一般使用new LinkedBlockingQueue<Runnable>()这个,如果不指定容量,会一直往里边添加,没有限制,workQueue永远不会满,一般选择没有容量上限的队列;
threadFactory:创建线程的工厂,使用系统默认的类
handler:当任务数超过maximumPoolSize时,对任务的处理策略,默认策略是拒绝添加

----执行流程:当线程数小于corePoolSize时,每添加一个任务,则立即开启线程执行当corePoolSize满的时候,后面添加的任务将放入缓冲队列workQueue等待;当workQueue也满的时候,看是否超过maximumPoolSize线程数,如果超过,默认拒绝执行,如果没有超过,则创建线程立即执行。
举例说明:
假如:corePoolSize=2,maximumPoolSize=3,workQueue容量为8;最开始,执行的任务A,B,此时corePoolSize已用完,再次执行任务C,则C将被放入缓冲队列workQueue中等待着,如果后来又添加了7个任务,此时workQueue已满,则后面再来的任务将会和maximumPoolSize比较,由于maximumPoolSize为3,因为有2个在corePoolSize中运行了,所以只能容纳1个了,那么会立即创建线程执行。那么后面来的任务默认都会被拒绝--通常都会报异常。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值