Android 线程和线程池

Android线程的销毁 在Android开发中,经常会用到线程和Timer,如果没有主动关闭它们,当程序结束时,线程并没有被销毁,而是一直在后台运行着,当我们重新启动应用时,又会重新启动一个线程,周而复始,你启动应用次数越多,开启的线程数就越多,你的机器就会变得越慢。还会导致意想不到的错误 立即下载

本文 Github 地址:
https://github.com/YoungBear/MyBlog/blob/master/ThreadPool.md
参考《Android 开发艺术探索》

Stop saying “I wish” and start saying “I will”.

不要再说“我希望…”,开始说“我会…”。

线程池的优点

  1. 重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销
  2. 能有效控制线程池的最大并发数,避免大量的线程之间因互相抢占系统资源而导致的阻塞现象
  3. 能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能。

      Android 中的线程池的概念来源于 Java 中的 Executor, Executor 是一个接口,真正的线程池的实现为 ThreadPoolExecutor。ThreadPoolExecutor 提供了一系列参数来配置线程池,通过不同的参数可以创建不同的线程池,从线程池的功能特性上来说,Android 的线程池主要分为 4 类,这 4 类线程池可以通过 Executor 所提供的工厂方法来得到。由于 Android 中的线程池都是直接或者间接通过配置 ThreadPoolExecutor 来实现的,所以先了解下 ThreadPoolExecutor。

package java.util.concurrent;

ThreadPoolExecutor.java

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

corePoolSize

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

maximumPoolSize

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

keepAliveTime

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

unit

  用于指定 keepAliveTime 参数的时间单位。

workQueue

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

threadFactory

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

handler

  当线程池无法执行新任务时,这个能是由于任务队列已满或者是无法成功执行任务,这个时候 ThreadPoolExecutor 会调用 handler 的 rejectedExecution 方法来通知调用者,默认情况下 rejectedExecution 方法会直接抛出一个 RejectedExecutionException。

  ThreadPoolExecutor 执行任务时大致遵循如下规则:

  1. 如果线程池中的线程数量未达到核心线程的数量,那么会直接启动一个核心线程来执行任务。
  2. 如果线程池中的线程数量已经达到或者超过核心线程的数量,那么任务会被插入到任务队列中排队等待执行。
  3. 如果在步骤 2 中无法将任务插入到任务队列中,这往往是由于任务队列已满,这个时候如果线程数量未达到线程池规定的最大值,那么会立即启动一个非核心线程来执行任务。
  4. 如果步骤 3 中线程数量已经达到线程池规定的最大值,那么就拒绝执行此任务,ThreadPoolExecutor 会调用 RejectedExecutionHandler 的 rejectedExecution 方法来通知调用者。

AsyncTask 中 ThreadPoolExecutor 的配置

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE = 1;

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
        }
    };

    private static final BlockingQueue<Runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<Runnable>(128);

    /**
     * An {@link Executor} that can be used to execute tasks in parallel.
     */
    public static final Executor THREAD_POOL_EXECUTOR
            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

  从上面的代码可以知道,AsyncTask 对 THREAD_POOL_EXECUTOR 这个线程池进行了配置,配置后的线程池规格如下:

  核心线程数等于 CPU 核心数 + 1;

  线程池的最大线程数为 CPU 核心数的 2 倍 + 1;

  核心线程无超时机制,非核心线程在闲置时的超时时间为 1 秒;

  任务队列的容量为 128。

Android 中最常用的四类线程池

  FixedThreadPool

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

  FixedThreadPool 是一种线程数量固定的线程池,并且只有核心线程。当线程处于空闲状态时,他们并不会被回收。当所有的线程都处于活动状态时,新任务都会处于等待状态,直到有线程空闲出来。由于 FixedThreadPool 只有核心线程并且这些核心线程不会被回收,这意味着它能够更加快速地相应外界的请求。

  特点:

  1. 线程数量固定
  2. 只有核心线程
  3. 没有超时机制
  4. 任务队列没有大小限制

CachedThreadPool

   public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

  CachedThreadPool 是一种线程数量不定的线程池,它只有非核心线程,并且其最大线程数为 Integer.MAX_VALUE 。由于 Integer.MAX_VALUE 是一个很大的数,实际上就相当于最大线程数可以任意大。当线程池中的线程都处于活动状态时,线程池会创建新的线程来处理新任务,否则就会利用空闲的线程来处理新任务。线程池中的空闲线程都有超时机制,这个超时时长为 60 秒,超过 60 秒闲置线程就会被回收。和 FixedThreadPool 不同的是, CacheedThreadPool 的任务队列其实相当于一个空集合,这将导致任何任务都会立即被执行,因为在这种场景下 SynchronousQueue 是无法插入任务的。从 CacheThreadPool 的特性来看,这类线程池比较适合执行大量的耗时较少的任务。当整个线程池都处于闲置状态时,线程池中的线程都会超时而被停止,这个时候 CachedThreadPool 之中实际上是没有任何线程的,它几乎是不占用任何系统资源的。

  特点:

  1. 线程数目不固定
  2. 只有非核心线程
  3. 最大线程数任意大
  4. 有超时机制,闲置线程超过 60 秒就会被回收
  5. 任务队列为空集合,任何任务都会立即被执行

      ScheduledThreadPool

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

  ScheduledThreadPool 的核心线程数量是固定的,而非核心线程数是没有限制的,并且当非核心线程闲置时会被立即回收。ScheduledThreadPool 这类线程池主要用于执行定时任务和具有固定周期的重复任务。

  特点:

  1. 核心线程固定
  2. 非核心线程任意大
  3. 有超时机制,闲置线程会被立即(0秒)回收

      SingleThreadExecutor

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

  SingleThreadExecutor 线程池内部只有一个核心线程,它确保所有的任务都在同一个线程中按顺序执行。SingleThreadExecutor 的意义在于统一所有的外界任务到一个线程中,这使得在这些任务之间不需要处理线程同步的问题。

  特点:

  1. 只有一个线程

测试小程序

Github地址:

https://github.com/YoungBear/JavaLearn/blob/master/src/com/example/executor/Test.java

/**
 * 
 */
package com.example.executor;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author bearyang
 *
 */
public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Runnable command = new Runnable() {

            @Override
            public void run() {
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String timeString = format.format(new Date());
                System.out.println("current: " + timeString);
            }
        };

        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
        fixedThreadPool.execute(command);

        ExecutorService cacheThreadPool = Executors.newCachedThreadPool();
        cacheThreadPool.execute(command);

        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4);
        // 2000ms后执行command
        scheduledExecutorService.schedule(command, 2000, TimeUnit.MILLISECONDS);
        // 延迟10s后,每隔1s执行一次command
        scheduledExecutorService.scheduleAtFixedRate(command, 10 * 1000, 1000, TimeUnit.MILLISECONDS);

        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        singleThreadExecutor.execute(command);
    }

}
管道机器人手臂机械结构设计cad【8张】+三维图+设计说明书+绛重 履带式管道机器人适用于各种管道环境,包括直管道、弯曲管道、水平管道、垂直管道等,其灵活性和适应性使得它可以应对不同形状和尺寸的管道,完成全面的检测和维护工作。管道机器人研究具有重要的现实意义和深远的社会影响,通过提高工作效率、降低人员风险、提升服务质量、节约成本资源和促进科技创新等方面的作用,为现代工程技术领域的发展和进步做出了积极的贡献。管道机器人是一种能够在管道内部执行各种任务的智能机器人,而管道机器人的机械臂对于管道机器人在管道内执行任务的灵活性、稳定性和效率至关重要。 阅读详情

相关推荐

STM32L452与FPGA通信翻车?手把手教你关闭I2C时钟延展避坑(附OVR错误解决方案)

本文深入解析STM32L452与FPGA在I2C通信中因时钟延展功能导致的常见问题,提供关闭I2C时钟延展的详细配置方法(NOSTRETCH模式),并针对可能出现的OVR错误给出Combined模式解决方案。通过实战案例和波形分析,帮助工程师快速排查和解决嵌入式系统中的I2C兼容性问题。

e3f4g5的博客 216

Android 系统开发 - 进程管理之内存的回收

前言内存是系统中非常宝贵的资源,即便如今的移动设备上,内存已经达到4G甚至6G的级别,但对于内存的回收也依然重要,因为在Android系统上,同时运行的进程有可能会有几十甚至上百个之多。如何将系统内存合理的分配给每个进程,以及如何进行内存回收,便是操作系统需要处理的问题之一。本文会讲解Android系统中内存回收相关的知识。对于内存回收,主要可以分为两个层次:进程内的内存回收:通过释放进程中的资源...

Android技术之家 915

头歌操作系统2.3系统调用命令ls执行的系统调用

设置版本0内核为分析对象。然后一直c直到虚拟机出现。然后一直c就是答案了。

m0_74128952的博客 1万+

android线程自动回收,Android AsyncTask使用旧数据回收的线程

我试图通过从Activity调用的Asynctask访问REMOTE android服务。Android AsyncTask使用旧数据回收的线程我有一个问题,我认为是线程被重用造成的。我在AsyncTask中使用了一个Lopper,当它得到一个线程时,它已经被一个早期的远程服务调用分配了,我得到一个关于每个线程只允许有一个循环的错误。我不认为这是因为我试图在错误的线程上访问UI。我可以用一些非常简...

weixin_34354231的博客 610

ENVI5.6 Seamless Mosaic多景影像镶嵌色差问题

多景影像无缝镶嵌色差问题拟解决方法

Matchaya的博客 7705

Oracle-如何修复undo坏快

undo出现坏快,导致数据库宕机,无法启动

qqqyyy0422的博客 570

Android NDK thread 回收crash, signal 4 (SIGILL), code 1 (ILL_ILLOPC) , fault addr 地址

Android NDK thread 回收crash, signal 4 (SIGILL), code 1 (ILL_ILLOPC) , fault addr 地址 在NDK c++ 使用pthread_create 创建线程,不管是可分离线程还是非可分离的线程,在回收的时候都有这个问题。 最后在网上找了一篇, 试了一下, 解决了。 下面列下出错的代码: bool falg = true; sta...

nianshao163的博客 1886

在iPad上使用Python进行编程

如果你拥有一台iPad,并且想在上面编写和运行Python代码,你会发现iPad提供了一些适用的工具和应用程序来满足你的需求。安装一个Python解释器应用程序,编写和运行Python代码,使用第三方库和模块,以及存储和共享代码,这些步骤将帮助你在iPad上进行Python编程。要在iPad上运行Python代码,首先需要安装一个Python解释器。这些应用程序提供了一个交互式的开发环境,允许你编写、编辑和运行Python代码。一旦你安装了Python解释器应用程序,你可以开始编写Python代码了。

2301_79366435的博客 4628

Android 线程池

1.线程 在了解线程池之前,先给大家介绍下线程的概念。 从底层角度来说: 一个线程就是在进程中的一个单一的顺序控制流.。 而单个进程可以拥有多个并发执行的任务,每个任务都好像有自己的CPU一样,而其底层的机制就是切分CPU的时间,也就是CPU将轮流给每个任务分配其占用时间。每个任务都觉得自己在一直占用CPU,而事实上是将CPU时间划分成片段分配给所有的任务。 在多个CPU的环境下,多线程的运作,可以极大的提供程序的运行速度,这就是线程存在的意义。 在Android中,有进程和线程之分: 进程:每个app运行

zenmela2011的专栏 8511

利用 SAP Joule 提升 ABAP 开发效率的前提条件与限制全解析

综上,想要在 ABAP Development Tools 中顺利使用 SAP Joule,既要准备好 BTP、IAS、ABAP 系统与 ADT 的版本与信任链,也要理解许可证、配额、语法范围等限制。只有在这些前提全部满足后,Joule 才能真正发挥生成式 AI 的价值,帮助 ABAP 开发者从繁琐模板中解放出来,把注意力投入在业务创新与 Clean Core 改造之上。未来 SAP 还将扩展中文语境、自动修复建议以及跨系统智能代理等功能,值得持续关注。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 664

【模型实战】MiMo-VL-7B讲解与实战

维度成绩MMMU70.6(图像理解最难测试之一)VideoMME70.8(视频理解标杆)59.4(超越78B参数模型)56.1(超过专用GUI模型)Elo评分开源VLM排名第一(7B~72B)社区热度过去一个月下载超1,600次(RL+SFT)📌一句话概括MiMo-VL 是目前性能最强、推理最稳、体验最佳、生态最全的7B级开源视觉语言模型。

m0_47867638的博客 1199

Android中线程池

阻塞队列常用于生产者消费者场景,生产端负责生产,生产的东西发往消费者端。其中生产者端就是往这个阻塞队列添加元素的线程,消费者端就是从队列中拿出元素的线程。

m0_61130325的博客 3133

无人船 | 基于ROS的轻量级多无人艇自主导航仿真框架

无人水面艇USV是海上自主无人系统的关键组成部分,在民用、军用领域应用广泛,例如海上救援、水质测量、扫雷反潜等,因此对USV导航算法的研究具有重要意义。为了便于进行USV相关算法的验证与部署,本文介绍的这套基于ROS的多无人艇的自主导航仿真平台,轻量化地实现了建图、规划、控制等多种功能,同时自研框架保证了功能的高度可拓展和可定制

FRIGIDWINTER的博客 8009

《Android开发艺术探索》之安卓的线程和线程池(十三)

第11章 Android的线程和线程池 线程分为主线程和子线程,主线程负责处理UI界面操作,子线程负责执行耗时操作,由于Android的特性,主线程执行耗时过长就会ANR。除了Thread本身之外,AsyncTask、IntentServi...

云瀚的自习室 1008

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Android:Android线程和线程池的作用

这篇笔记是笔者关于Android线程和线程池作用的学习记录

qjyws的博客 1800

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Android的线程和线程池

线程分别主线程和子线程。在Android中,主线程也就是UI线程。在Android中,除了Thread本身以外,在Android中扮演线程角色的还有很多:AsyncTask、IntentService以及HandlerThread。对AsyncTask来说,底层使用了线程池。对与IntentService和HandlerThread来说,它们的底层则直接使用了线程。HandlerThread是一种特殊的线程,具有消息循环的线程,在它内部可以直接使用Handler。

huaihong1986的博客 1020

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

android 简书 线程池,Android的线程和线程池

从用途上来说,线程分为主线程和子线程,主线程主要处理和界面相关的事情,子线程则往往用于执行耗时操作。除了Thread本身以外,在Android中可以扮演线程角色的还有很多:AsyncTak、IntentService和HandlerThread。AsyncTask:底层用到了线程池;封装了线程池和Handler,主要是为了方便开发者在子线程中更新UIIntentService:底层直接使用线程,它...

weixin_39544333的博客 150

Android进阶知识——Android线程和线程池

文章目录1.主线程和子线程2.Android中的线程形态 本章的主题是Android中的线程和线程池。线程在Android中是一个很重要的概念,从用途上来说,线程分为主线程和子线程,主线程主要处理和界面相关的事,而子线程则往往用于执行耗时操作。除了Thread本身以外,在Android中可以扮演线程角色的还有很多,比如AsyncTask和IntentService,同时HandlerThread也是一种特殊的线程。尽管AsyncTask、IntentService以及HandlerThread的表现形式都有

ABded的博客 1071

android 线程池封装,Android的线程和线程池

线程分为主线程和子线程,主线程主要处理和界面相关的事情,而子线程则往往用于执行耗时操作。AsyncTask封装了线程池和Handler,它主要是为了方便开发者在子线程中更新UI。HandlerThread是一种具有消息循环的线程,在它的内部可以使用Handler。IntentService是一个服务,系统对其进行了封装使其可以更方便的执行后台任务,IntentService内部采用HandlerT...

weixin_29043895的博客 324

android线程池不工作了,Android线程和线程池

不同形式的线程虽然都是线程,但是它们仍然具有不同的特性和实用场景:AsyncTask封装了线程池和Handler,它主要是为了方便开发者在子线程中更新UIHandlerThread是一种具有消息循环的线程,在它的内部可以使用HandlerIntentService是一个服务,系统对其进行了封装使其可以更方便的执行后台任务,IntentService内部采用HandlerThread来执行任务,当任...

weixin_42511201的博客 604

Android线程池的原理和实践总结

提纲 是什么(使用线程池的原因,线程池的定义,好处,线程池原理) 怎么用(常见的使用方式,以及各个参数的作用) 为什么(源码分析,设计模式分析) 关于原理在android中的部分应用,部分注意事项 引子(原因) 多线程技术: 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力 多线程的异步执行...

WHHGARSKY的博客 2636

android 线程池 demo,Android的线程和线程池

前言线程在Android中是一个很重要的概念,从用途上来说,线程分为主线程和子线程,主线程主要处理和界面相关的事情,而子线程则往往用于执行耗时操作。由于Android的特性,如果在主线程中执行耗时操作那么就会导致程序无法及时地响应,因此耗时操作必须放在子线程中去执行。在操作系统中,线程是操作系统调度的最小单元,同时线程又是一种受限的系统资源,即线程不可能无限制的产生,并且线程的创建和销毁都会有相应...

weixin_39996141的博客 383
上一篇: Java修饰符 transient,volatile等
下一篇: Android AsyncTask源码分析
杨小熊的笔记
博客等级 码龄15年 125粉丝 156原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值