Android 中使用线程池

简介: Android 中使用线程池

系统创建一个线程的成本还是比较高的,因为他涉及与系统的交互,在这种情形下,使用线程池可以很好地提高性能,尤其是在程序中需要创建大量生存期比较短暂的线程时,就更应该使用线程池。


思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用。


好处:


提高响应速度(减少了创建新县城的时间)

降低资源消耗度(重复利用线程池中线程,不需要每次创建)

便于线程管理


使用线程池


ThreadPoolExecutor 是线程池的真正实现,他的构造方法提供了一系列的参数来配置线程池,下面看一下ThreadPoolExecutor的构造方法中各个参数的含义。


public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory)


corePoolSize : 线程的核心线程数。默认的情况下,核心线程会在线程池中一直存活,即他们处于闲置状态。如果将 ThreadPoolExecutor 的allowCoreThreadTimeOut()属性设置为 true ,那么闲置的核心线程在等待新任务到来时会有超时策略,这个时间由 keepAliveTime 所指定,当等待的时间超过 keepAliveTime所指定的时长后,核心线程会被终止。


maximumPoolSize : 线程池所能容纳的最大线程数,当活动线程数达到这个值后,后续的任务将会被阻塞。


keepAliveTime : 非核心线程闲置时 的超时时长,超过这个时间,非核心线程将会被回收。当 ThreadPoolExecutor 的 allowCoreThreadTimeOut 属性设置为true时,keepAliveTime 同样会作用于核心线程。


unit : 用于指定 keepAliveTime 的参数单位,这是一个枚举。常用的有 TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS(秒)等。


workQueue : 线程池中的任务队列,通过线程池的 execute 方法提交的 Runnable 对象会报存在这个参数中。


theadFactory : 线程工厂,为线程池提供创建线程 新线程的功能。ThreadFactory是一个接口,他只有一个方法,Thread newThread(Runnable r)。


ThreadPoolExecutor 执行任务的时候大致遵循入下规则:


如果线程池中的线程数量未达到 核心线程的数量,那么会直接启动一个核心线程来执行任务。

如果线程池中的核心数量 已经达到或者大于 核心线程数量,那么 任务会被插入到任务队列中排队等待执行。

如果在上一个步骤中 无法将任务插入到任务队列 ,这是由于任务虐队列已满,这个时候如果线程数量未达到线程池数量的最大值,则会启动一个非核心线程来执行任务,否则就会拒绝该任务。


线程池的分类


四种最常见且具有不同功能的线程池,他们都是直接或间接通过配置ThreadPoolExecutor 来实现 自己的功能特性。这四种分别是 FixedThreadPool 、CachedThreadPool、ScheduledThreadPool 以及 SingleThreadExecutor。


FixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}


通过 Executors 的new FixedThreadPool() 创建,他是一种线程数量固定的线程,当线程处于空闲状态时,他们并不会被回收,除非线程池关闭了。当所有线程池处于活动状态时,新任务就会处于等待状态,直到有线程空闲出来。


由于 FixedThreadPool 只有 核心线程并且这些线程不会被回收,这以为这他能够正确的响应外界的请求。


public static void main(String[] args){
    ExecutorService executorService = Executors.newFixedThreadPool(2);
    executorService.execute(new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    });
    executorService.execute(new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    });
    executorService.execute(new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    });
}


结果如下:


pool-1-thread-1

pool-1-thread-2

pool-1-thread-1


CachedThreadPool


return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                              60L, TimeUnit.SECONDS,
                              new SynchronousQueue<Runnable>());


通过 Executors 的new CachedThreadPool() 创建,他是一种线程数量不定的线程池,他只有非核心线程,并且最大线程数为 Integer.MAX_VALUE, 由于Integer.MAX_VALUE 是一个很大的数,实际上就相当于任意大。


当线程池中的 线程都处于活动状态时,线程池就会创建新的线程来处理新的任务。否则就用空线程来处理任务。


线程池中空线程都有超时机制,这个超时时长为60秒,超过60秒闲置线程就会被回收。


从 CachedThreadPool 的特性上来看,这类线程池比较适合执行 大量的耗时较少的任务。当整个线程池中都处于闲置状态时,线程池中的线程就会因为超时而停止。这个时候 CachedThreadPool 之中是没有任何线程的,他几乎是不占用任何系统资源的。


ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new Runnable() {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
});


ScheduledThreadPool
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}
   public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE,
              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
              new DelayedWorkQueue());
    }


通过 Executors 的new ScheduledThreadPool() 创建, 他的核心线程数量是固定的,而非核心线程数 是没有限制的,并且当非核心线程 闲置时 会被立刻进行回收。


ScheduledThreadPool 这类线程主要用于指定定时任务和具有固定周期的重复任务。


public static void main(String[] args){
    ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
    executorService.execute(new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    });
}


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


通过 Executors 的new SingleThreadExecutor() 创建,这类线程内部只有一个核心线程,他确保所有的任务都是在同一个线程按顺序执行,


SingleThreadExecutor 的意义在于统一外界的任务到一个线程中,这使得这些任务之间不需处理同步的问题。


ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(new Runnable() {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
});
executorService.execute(new Runnable() {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
});


结果如下:


pool-1-thread-1

pool-1-thread-1


上面对 常见的四种线程 进行了详细的介绍,除了上面系统提供的四种线程外,也可以根据时间需要灵活的配置线程。


相关文章
|
7月前
|
Java Android开发 UED
🧠Android多线程与异步编程实战!告别卡顿,让应用响应如丝般顺滑!🧵
【7月更文挑战第28天】在Android开发中,确保UI流畅性至关重要。多线程与异步编程技术可将耗时操作移至后台,避免阻塞主线程。我们通常采用`Thread`类、`Handler`与`Looper`、`AsyncTask`及`ExecutorService`等进行多线程编程。
77 2
|
2月前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。
|
7月前
|
Java Android开发
Android面试题经典之Glide取消加载以及线程池优化
Glide通过生命周期管理在`onStop`时暂停请求,`onDestroy`时取消请求,减少资源浪费。在`EngineJob`和`DecodeJob`中使用`cancel`方法标记任务并中断数据获取。当网络请求被取消时,`HttpUrlFetcher`的`cancel`方法设置标志,之后的数据获取会返回`null`,中断加载流程。Glide还使用定制的线程池,如AnimationExecutor、diskCacheExecutor、sourceExecutor和newUnlimitedSourceExecutor,其中某些禁止网络访问,并根据CPU核心数动态调整线程数。
196 2
|
3月前
|
API Android开发 iOS开发
深入探索Android与iOS的多线程编程差异
在移动应用开发领域,多线程编程是提高应用性能和响应性的关键。本文将对比分析Android和iOS两大平台在多线程处理上的不同实现机制,探讨它们各自的优势与局限性,并通过实例展示如何在这两个平台上进行有效的多线程编程。通过深入了解这些差异,开发者可以更好地选择适合自己项目需求的技术和策略,从而优化应用的性能和用户体验。
|
4月前
|
调度 Android开发 开发者
构建高效Android应用:探究Kotlin多线程优化策略
【10月更文挑战第11天】本文探讨了如何在Kotlin中实现高效的多线程方案,特别是在Android应用开发中。通过介绍Kotlin协程的基础知识、异步数据加载的实际案例,以及合理使用不同调度器的方法,帮助开发者提升应用性能和用户体验。
91 4
|
5月前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android多线程编程的重要性及其实现方法,涵盖了基本概念、常见线程类型(如主线程、工作线程)以及多种多线程实现方式(如`Thread`、`HandlerThread`、`Executors`、Kotlin协程等)。通过合理的多线程管理,可大幅提升应用性能和用户体验。
177 15
一个Android App最少有几个线程?实现多线程的方式有哪些?
|
5月前
|
Java Android开发 UED
🧠Android多线程与异步编程实战!告别卡顿,让应用响应如丝般顺滑!🧵
在Android开发中,为应对复杂应用场景和繁重计算任务,多线程与异步编程成为保证UI流畅性的关键。本文将介绍Android中的多线程基础,包括Thread、Handler、Looper、AsyncTask及ExecutorService等,并通过示例代码展示其实用性。AsyncTask适用于简单后台操作,而ExecutorService则能更好地管理复杂并发任务。合理运用这些技术,可显著提升应用性能和用户体验,避免内存泄漏和线程安全问题,确保UI更新顺畅。
178 5
|
5月前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android应用开发中的多线程编程,涵盖基本概念、常见实现方式及最佳实践。主要内容包括主线程与工作线程的作用、多线程的多种实现方法(如 `Thread`、`HandlerThread`、`Executors` 和 Kotlin 协程),以及如何避免内存泄漏和合理使用线程池。通过有效的多线程管理,可以显著提升应用性能和用户体验。
151 10
|
5月前
|
API Android开发 iOS开发
安卓与iOS开发中的线程管理对比
【9月更文挑战第12天】在移动应用的世界中,安卓和iOS平台各自拥有庞大的用户群体。开发者们在这两个平台上构建应用时,线程管理是他们必须面对的关键挑战之一。本文将深入探讨两大平台在线程管理方面的异同,通过直观的代码示例,揭示它们各自的设计理念和实现方式,帮助读者更好地理解如何在安卓与iOS开发中高效地处理多线程任务。
|
5月前
|
Java Android开发 开发者
安卓应用开发中的线程管理优化技巧
【9月更文挑战第10天】在安卓开发的海洋里,线程管理犹如航行的风帆,掌握好它,能让应用乘风破浪,反之则可能遭遇性能的暗礁。本文将通过浅显易懂的语言和生动的比喻,带你探索如何优雅地处理安卓中的线程问题,从基础的线程创建到高级的线程池运用,让你的应用运行更加流畅。

热门文章

最新文章

  • 1
    如何修复 Android 和 Windows 不支持视频编解码器的问题?
  • 2
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 3
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
  • 4
    【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
  • 5
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
  • 6
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 7
    Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
  • 8
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 9
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
  • 10
    Android学习自定义View(四)——继承控件(滑动时ListView的Item出现删除按钮)