#Android学习计划##第1期#-----线程池一之入门总结


一、简易图帮助我们更好更快的理解线程池:

 

二、 理解线程池?

         大家都遇到过一个问题,我们忙碌了一周之后,周末终于可以去享受一下。吃一顿自己最爱吃的火锅。结果女朋友化妆吗太磨叽,导致去了就1点多了,正是用餐的高峰期,火锅店一共有30个桌子,已经全部占满,而且还有10位在排队,你想放弃,但是拗不过你对象,只能等待了。

          从上面的例子中可以看出,火锅店是一个线程池(准确来说房子是一个线程池)、顾客是将要执行的线程、当桌位满员,也就是核心线程达到最大数量的时候,我们只能在阻塞队列里面等待。当都满员的时候,老板想快速一点,会说,大家如果有不介意的,走廊也是可以坐的,这个走廊就好比我们除了核心线程池以外的区域也就是非核心线程。当非核心线程也满时,如果还有人继续的进入火锅店,老板会说,我们今儿人员已经爆满了,请您明日再来吧,这就是线程池抛出异常。

三、线程池的构造:

  1. 线程池的构造参数:corePoolSize:线程池中核心线程的数量。                                                                                                                              maximumPoolSize:线程池中最大线程数量。                                                                                                                           keepAliveTime:非核心线程的超时时长,当系统中非核心闲置时间超过该时间的时候被回收。                                             unit:该为keepAlivePoolSize的单位,有纳秒、微秒、毫秒、秒、分、时、天等                                                                     workQueue:线程池中的任务队列,用来存放已经被提交但尚未执行的任务。要用execute                                                   workQueue是一个BlockingQueue类型,当我们读取新的数据的时候,如果该队列是空的,则取数据的操作将会变成阻塞状态,当该队列有了新的数据的时候,再继续进行操作。当BloickingQueue , 队列中的队列满员的时候,也会变成阻塞状态,  有新的空间的时候就重新被唤醒。                                                                                                                                           1)、 ArrayBlockingQueue(数组队列):它的构造函数接收一个int类型的值,然后存在该数组队列。遵循先进先出的原则,规定了大小。                                                                                                                                                                      2)、LinkedBlockingQueue:(链队列):在其构造函数中接收一个int类型的值,这样可以来规定改队列的大小,如果不传的话,链表的长度不固定,最大值为max_value.                                                                                                                    3)、PriorityBlockingQueue:                                                                                                                                                    4)、SynchronousQueue:这个是同步线程的队列,属于线程安全。内部没有数据缓存空间。一对一的模式,互相牵制的对方 。                                                                                                                                                                               hreadFactory:为线程池创建新线程的功能。                                      

四、 线程池的几种模式:

                                       1、FixedThreadPool(我叫热水池):newFixedThreadPool来创建此线程,该线程中所有的线程都均为核心线程,没有超时机制,排队任务机制也无限制。相应比较快。

                           2、CachedThreadPool(我叫缓存池):通过newCacheThreadPool的方法来创建,为什么叫缓存池呢,不光是因为见名识意,因为它这个线程池中没有核心线程数,都是非核心线程,给我的感觉这些线程就是被存放在这个大池子中,有需要执行的线程的时候直接创建并分配线程进行执行。适合做一些无间断大量但是功耗比较小的任务。超时时间为60s,当线程闲置60s会自动被回收,所以也不会造成占用浪费资源的线程。

                             3、ScheduledThreadPool(超级池):为什么叫超级池呢,是因为它完美的融合了FixedThreadPool和CacheThreadPool这俩者。它不但有固定的核心线程数,而且还有无限量的非核心线程数。并且它的非核心线层的超时时间设置的为0s,一旦非核心线程空闲的时候就会回收,适合我们做一些定时的任务。比如前段时间项目中有querystatus就是可以使用。

                             4、SingleThreadExecutor(超累池):为什么叫超累池呢?因为它的池中只有一个核心的线程来执行任务,顺序执行,层层都需要自己把关,自己做,就想不会带团队的领导,累死也干不成大事。

五、线程池的实际应用:

       //个人练习写的,望大神纠正

public class ExecuteThread {
    //核心线程数
    int corePoolSize;
    //最大线程数=核心线程数+非核心线程数
    int maximumPoolSize;
    //非核心线程超时时间
    long keepAliveTime=1L;
    //非核心线程超时时间单位
    TimeUnit unit=TimeUnit.MINUTES;
    //线程池中的任务队列
    BlockingQueue<Runnable> workQueue;
    //线程工厂
    ThreadFactory nThreadFactory;

    private static ExecuteThread instance = null;

    private ExecuteThread() {
    }

    public static ExecuteThread getInsatnce() {
        if (instance == null) {
            instance = new ExecuteThread();
        }
        return instance;
    }

    //创建线程工厂
    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        // AtomicInteger可以在并发情况下达到原子化更新,避免使用了synchronized,而且性能非常高
        private final AtomicInteger mCount = new AtomicInteger(1);

        @Override
        public Thread newThread(@NonNull Runnable r) {
            return new Thread(r, mCount.getAndIncrement() + "");
        }
    };
//核心线程池,创建的线程都是核心线程,没有超时机制,排队队列也无限制
    public static ExecutorService newFixedThreadPool(int nThread) {
        return new ThreadPoolExecutor(nThread, nThread,
                keepAliveTime, unit, new LinkedBlockingQueue<Runnable>(), sThreadFactory);
    }
}

//实际应用:

 public void test(){
            //直接调用该方法
        ExecutorService executorService = ExecuteThread.newFixedThreadPool(5);
        Runnable myRunnable = new Runnable() {
            @Override
            public void run() {
                //执行我们一些耗时操作。
            }
        };
//提交到线程池
        executorService.execute(myRunnable);
    }

ps:细心的网友会发现会有这样的疑问,为什么你写了单例,为啥不用,而是直接类名.方法呢?哈哈,皮一下。是因为我在定义线程池的方法时把方法定义成了静态变量,所以直接类名.方法名。。。。。。去掉静态就可以使用单例来操作了。哈哈,不要打我。

延伸:private final AtomicInteger mCount = new AtomicInteger(1);

不知道大家有没有见过这个类,在上网浏览,查阅代码的时候看到的,然后简单的了解了一下。AtomicInteger是在非租塞算法实现并发控制。在并发的情况下达到原子化的更新,避免使用synchronized关键字,而且性能非常高。

六、后言:

        之前也不是很了解线程池,停留在会用的层面,也一直么有总结,今儿就先总结一些简单层面的知识点。希望能帮助到大家,后续还会继续往深层次的研究有关于线程池的文章。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值