Android线程池详解
来源:互联网 发布:linux目录权限 编辑:程序博客网 时间:2024/06/15 21:33
最近在看OkHttp的源码,看着看着就看到了有线程池的地方,以前自己对这个东西就也就感到云里雾里的,所以
想把线程池的知识点和源码完整的看一篇
1.线程池有什么用?
a.重用线程池中存在的线程,避免因为线程的大量创建和销毁所带来的性能开销 ,完成一项任务的时间T=创建线
程的时间+在线程中执行任务的时间+线程销毁的时间, 而线程池的出现可以大大减少创建线程的时间和线程销毁的
时间,从而提高app的性能
b.能有限的控制线程池的最大并发数,并且大量的线程互相抢占资源而导致的阻塞现象
c.对线程池中线程进行有效的跟进,当我们不需要处理的时候可以将它shutdow掉
并提供定时执行以及制定间隔循环执行,
2.ThreadPoolExcutor类详解
threadPoolExcutor是线程池中最核心的类,所以要想弄懂线程池一定要弄懂这个类
(1)首先来了解一下构造方法:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler);接下来看看具体每个参数是什么意思?
corePoolSize:核心线程池大小
maximumPoolSize:最大线程池大小
keepAliveTime:当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,
如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉。
unit:keepAliveTime时间单位
workQueue:阻塞任务队列
threadFactory:新建线程工厂
handler: 当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来做拒绝处理
(2)BlockingQueue详解:用于保存等待执行的线程任务的阻塞队列
ArrayBlockingQueue(少):是一个基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序。
LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue 静态工厂方法Executors.newFixedThreadPool()使用了这个队列,如果不执行队列的大小,那么该
队列就是一个无界队列,无界队列的特征见PriorityBlockingQueue
SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,它将任务直接提交给线程而不保持它们。在此,如果不存在可用于立即运行任务的线程,则试图把任务加入队列将失败,因此会构造一个新的线程
PriorityBlockingQueue(少):一个具有优先级的无限阻塞队列,使用无界队列将导致将导致在所有 corePoolSize 线程都忙时新任务在队列中等待。这样,创建的线程就不会超过 corePoolSize。(因此,maximumPoolSize和keepAliveTime的值也就无效了)
(3)ThreadFactory作用:
线程工厂,主要用来根据提交的新任务创建线程对象
static class PicassoThreadFactory implements ThreadFactory { @SuppressWarnings("NullableProblems") public Thread newThread(Runnable r) { return new Thread(r); } }
(4)ThreadPoolExcutor的执行步骤
①、当调用 execute() 方法添加一个任务时,线程池会做如下判断:
a. 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务;
b. 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列。
c. 如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创建线程运行这个任务;
d. 如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会抛出异常,告诉调用者
“我不能再接受任务了”。
②、当一个线程完成任务时,它会从队列中取下一个任务来执行。
③、当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于
corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。
这个过程说明,并不是先加入任务就一定会先执行。假设队列大小为 4,corePoolSize为2,maximumPoolSize为6,
那么当加入15个任务时,执行的顺序类似这样:首先执行任务 1、2,然后任务3~6被放入队列。这时候队列满了,
任务7、8、9、10 会被马上执行,而任务 11~15 则会抛出异常。最终顺序是:1、2、7、8、9、10、3、4、5、6。
当然这个过程是针对指定大小的ArrayBlockingQueue<Runnable>来说,如果无界队列,那么3-15的任务都会加到队列
中
3.ThreadPoolExcutor的使用
(1)newFixedThreadPool(2)
//指定了corePoolSize与maximumPoolSize为2 ExecutorServicer pool=Executors.newFixedThreadPool(2); // 创建线程 Thread t1 = new MyThread(); Thread t2 = new MyThread(); Thread t3 = new MyThread(); // 将线程放入池中进行执行 pool.execute(t1); pool.execute(t2); pool.execute(t3); // 关闭线程池 pool.shutdown(); private class MtThread extends Thread{...}
(2)单任务线程池newSingleThreadExecutor()
//只会有一个线程执行
ExecutorService pool = Executors.newSingleThreadExecutor();
(3).不限制大小,可变尺寸的线程池newCachedThreadPool()
//可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。
ExecutorService pool = Executors.newCachedThreadPool();
(4).延迟线程池,newScheduledThreadPool
// 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。 ScheduledExecutorService pool = Executors.newScheduledThreadPool(2); // 创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口 Thread t1 = new MyThread(); Thread t2 = new MyThread(); Thread t3 = new MyThread(); // 将线程放入池中进行执行 pool.execute(t1); // 使用延迟执行风格的方法 pool.schedule(t2, 1000, TimeUnit.MILLISECONDS); pool.schedule(t3, 10, TimeUnit.MILLISECONDS); // 关闭线程池 pool.shutdown();
以上就是Executors类的四种静态创建线程池的方法,如果不能满足需求,还可以通过实例化ThreadPoolThread
来自定义线程池
(5)ThreadPoolExecutor中几个重要的方法
① execute(Runnable r):向线程池添加一个线程任务
② Future<?> submit(Runnable r):向线程池添加一个线程任务,可以返回任务执行结果
③ shutdown():关闭线程池,不接收新的任务,关闭后,正在等待执行的任务不受任何影响,会正常执行,无返回值!
④ shutdownNow():关闭线程池,也不接收新的Task,并停止正等待执行的Task(也就是说,
执行到一半的任务将正常执行下去),最终还会给你返回一个正在等待执行但线程池关闭却没有被执行的Task集合
我们执行Runnable任务,他的run()方法是没有返回值的,那如果我们想要执行完一个任务,并且能够拿到一个返回值结果,那么应该怎么做呢?这个在我的另一篇博客已经将的很清楚了就不重复讲了Future和Callable详解
- Android 线程池详解
- Android 线程池详解
- Android线程池详解
- Android线程池详解
- Android线程池详解
- Android 线程池详解
- Android线程池详解
- Android(线程二) 线程池详解
- Android(线程二) 线程池详解
- Java(Android)线程池详解
- Android线程池ThreadPoolExecutor详解
- Android线程池使用详解
- 详解Android线程池ThreadPoolExecutor的教程
- android线程池详解(一)
- Android线程池ThreadPoolExecutor参数详解
- Android 线程池框架、Executor、ThreadPoolExecutor详解
- Android 线程池框架、Executor、ThreadPoolExecutor详解
- Android 的线程(AsyncTask、HandlerThread、IntentService详解)和线程池
- Java集合框架(List, Set, Map, Collections)
- C语言学习11
- svn linux服务器回退版本
- dom4j操作xml文件整理
- Lombok 学习
- Android线程池详解
- java系统运维:使用java自带的工具监控系统(java)虚机的运行
- 手机浏览器下判断是否安装某app,并判断是否打开该应用
- 使用Spring进行面向方面编程
- form表单回车ajax提交
- HTML5创建的简易web表单
- HDU 2604 Queuing [递推]【矩阵快速幂】
- 如何在Eclipse中查看Java类库的源代码以及相应的api
- php数组和xml之间相互转化