当前位置:   article > 正文

Android线程池理解_android cachedthreadpool使用

android cachedthreadpool使用

为什么使用线程池

当我们需要频繁地创建多个线程进行耗时操作时,每次都通过new Thread实现并不是一种好 的方式,每次new Thread新建和销毁对象性能较差,线程缺乏统一管理,可能无限制新建线程, 相互之间竞争,可能占用过多系统资源导致死锁,并且缺乏定时执行、定期执行、线程中断等功能。 好在Java提供了 4种线程池,它能够有效地管理、调度线程,避免过多的资源消耗,它强大到几 乎不需要幵发人员自定义的程度。它的优点如下:
  (1)    重用存在的线程,减少对象创建、销毁的幵销;
  (2)    可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞;
  (3)    提供定时执行、定期执行、单线程、并发数控制等功能。
线程池原理简单地解释就是会创建多个线程并且进行管理,提交给线程的任务会被线程池指派给 其中的线程进行执行,通过线程池的统一调度、管理使得多线程的使用更简单、高效。如下图所示。

 

基本的线程池 ThreadPoolExecutor

它的功能是启动指定数量的线程以及将任务添加到一个队列中,并且将任务分发给空闲的线程。ExecutorService 的生命周期包括三种状态:运行、关闭、终止。创建后便进入运行状态,当调用的 shutdown() 方法时,便进入关闭状态,此时意味着 ExecutorService 不再接受新的任务,但它还在执行已提交的任务。当所有已提交的任务执行完后,就变成终止状态。

ThreadPoolExecutor 的构造函数如下:

  1. public ThreadPoolExecutor(int corePoolSize,
  2. int maximumPoolSize,
  3. long keepAliveTime,
  4. TimeUnit unit,
  5. BlockingQueue<Runnable> workQueue,
  6. RejectedExecutionHandler handler)

下面对这几个参数详细说明:

ThreadPoolExecutor 的使用流程:

  1. /**
  2. * 1.创建基本线程池
  3. * corePoolSize:该线程池中核心线程的数量。
  4. * maximumPoolSize:最大线程数量
  5. * keepAliveTime:非核心线程空闲时要等待下一个任务到来的时间
  6. * unit:上面时间属性的单位
  7. * workQueue:任务队列
  8. */
  9. ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
  10. 3,
  11. 5,
  12. 1,
  13. TimeUnit.SECONDS,
  14. new LinkedBlockingQueue<Runnable>(100));
  15. /**
  16. * 2. 向线程池提交任务:execute()
  17. */
  18. threadPool.execute(new Runnable() {
  19. @Override
  20. public void run() {
  21. // 线程执行任务
  22. }
  23. });
  24. /**
  25. * 3. 关闭线程池shutdown()
  26. * 也可调用shutdownNow()关闭线程:threadPool.shutdownNow()
  27. * shutdown:设置 线程池的状态 为 SHUTDOWN,然后中断所有没有正在执行任务的线程
  28. * shutdownNow:设置 线程池的状态 为 STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表
  29. * 使用建议:一般调用shutdown()关闭线程池;若任务不一定要执行完,则调用shutdownNow()
  30. */
  31. threadPool.shutdown();

上面介绍的是基本的线程池 ThreadPoolExecutor 简单介绍,但这个并不是常用的;后面会介绍几种常用的线程池,它们都是根据 ThreadPoolExecutor 的基础上延伸的。

 

常用的线程池

启动指定数量的线程池 - FixedThreadPool

定时执行一些任务的线程池 - ScheduledThreadPool

可缓存的线程池 - CachedThreadPool

单个核线的线程池 - SingleThreadExecutor

 

这里面最常用的线程池是 FixedThreadPool ,下面来分别看一下它们的基本使用

 

启动指定数量的线程池 - FixedThreadPool

特点:该线程池只有核心线程,不会被回收;一般用于控制线程的最大并发数

  1. //创建线程池
  2. public ExecutorService mExecutor = Executors.newFixedThreadPool(5);
  3. //创建线程对象
  4. public class MyRunnable implements Runnable {
  5. private final int width;
  6. private final int height;
  7. public MyRunnable(int imageWidth, int imageHeight) {
  8. this.width = imageWidth;
  9. this.height = imageHeight;
  10. }
  11. @Override
  12. public void run() {
  13. //逻辑处理
  14. if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
  15. Log.e("wqs", "主线程: " + Thread.currentThread().getName());
  16. } else {
  17. Log.e("wqs", "不是主线程: " + Thread.currentThread().getName());
  18. }
  19. }
  20. }
  21. //向线程池添加任务
  22. private synchronized void startRunnable() {
  23. mExecutor.execute(new MyRunnable(100, 100));
  24. }
  25. //关闭线程池
  26. private void stopExecutor(){
  27. mExecutor.shutdown();
  28. }

当我们一直调用上面的 startRunnable() 方法时,可以看出最多有五个线程来处理我们的任务,如下图:

 

定时执行一些任务的线程池 - ScheduledThreadPool

特点:核心线程数量一定,非核心线程数量多个,闲置时会立马回收非核心线程数量;一般用于定时的任务

  1. //创建线程池
  2. public ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
  3. //创建线程对象
  4. public class MyRunnable implements Runnable {
  5. private final int width;
  6. private final int height;
  7. public MyRunnable(int imageWidth, int imageHeight) {
  8. this.width = imageWidth;
  9. this.height = imageHeight;
  10. }
  11. @Override
  12. public void run() {
  13. //逻辑处理
  14. if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
  15. Log.e("wqs", "主线程: " + Thread.currentThread().getName());
  16. } else {
  17. Log.e("wqs", "不是主线程: " + Thread.currentThread().getName());
  18. }
  19. }
  20. }
  21. //延迟开始执行
  22. private synchronized void startRunnable() {
  23. //延迟1s后执行任务
  24. scheduledExecutorService.schedule(new MyRunnable(100, 100), 1, TimeUnit.SECONDS);
  25. }
  26. //延迟开始执行循环任务
  27. private synchronized void startRunnableCycle() {
  28. //延迟100ms后、每隔1000ms执行任务
  29. scheduledExecutorService.scheduleAtFixedRate(new MyRunnable(100, 100),100,1000,TimeUnit.MILLISECONDS);
  30. }
  31. //关闭线程池
  32. private void stopExecutor(){
  33. scheduledExecutorService.shutdown();
  34. }

 

可缓存的线程池 - CachedThreadPool

特点:只有非核心线程,线程数量不固定;一般用于执行大量耗时少的任务

  1. //创建线程池
  2. public ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
  3. //创建线程对象
  4. public class MyRunnable implements Runnable {
  5. private final int width;
  6. private final int height;
  7. public MyRunnable(int imageWidth, int imageHeight) {
  8. this.width = imageWidth;
  9. this.height = imageHeight;
  10. }
  11. @Override
  12. public void run() {
  13. //逻辑处理
  14. if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
  15. Log.e("wqs", "主线程: " + Thread.currentThread().getName());
  16. } else {
  17. Log.e("wqs", "不是主线程: " + Thread.currentThread().getName());
  18. }
  19. }
  20. }
  21. //开始执行
  22. private synchronized void startRunnable() {
  23. cachedThreadPool.execute(new MyRunnable(100, 100));
  24. }
  25. //关闭线程池
  26. private void stopExecutor(){
  27. cachedThreadPool.shutdown();
  28. }

 

单个核线的线程池 - SingleThreadExecutor

特点:只有一个核心线程(是一个单线程);一般用于数据库操作

  1. //创建线程池
  2. public ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
  3. //创建线程对象
  4. public class MyRunnable implements Runnable {
  5. private final int width;
  6. private final int height;
  7. public MyRunnable(int imageWidth, int imageHeight) {
  8. this.width = imageWidth;
  9. this.height = imageHeight;
  10. }
  11. @Override
  12. public void run() {
  13. //逻辑处理
  14. if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
  15. Log.e("wqs", "主线程: " + Thread.currentThread().getName());
  16. } else {
  17. Log.e("wqs", "不是主线程: " + Thread.currentThread().getName());
  18. }
  19. }
  20. }
  21. //开始执行
  22. private synchronized void startRunnable() {
  23. singleThreadExecutor.execute(new MyRunnable(100, 100));
  24. }
  25. //关闭线程池
  26. private void stopExecutor(){
  27. singleThreadExecutor.shutdown();
  28. }

 

上面是对线程池的简单理解。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/240464
推荐阅读
相关标签
  

闽ICP备14008679号