Android中的线程

Android 中的线程池 Android 中的线程池: 线程池的优点: 重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销。 能有效控制线程池的最大并发数,避免大量的线程之间因互相抢占系统资源而导致的阻塞现象。 能够对线程进行简单管理,并提供定时执行以及指定间隔循环执行等功能。 ThreadPoolExecutor Android 中的线程池的概念来源于 Java 中的 Executor,Executor 是一个接口,真正的实现为 ThreadPoolExecutor。ThreadPoolExecutor 的构造方法中 阅读详情

Android中的线程形态除了传统的Thread以外,还包含AsyncTask、HandlerThread以及IntentService,这三者的底层实现也是线程,但是它们具有特殊的表现形式,同时在使用上也各有优缺点。

AsyncTask

AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程中更新UI。从实现上来说,AsyncTask封装了Thread和Handler,通过AsyncTask可以更加方便地执行后台任务以及在主线程中访问UI,但是AsyncTask并不适合进行特别耗时的后台任务,对于特别耗时的任务来说,建议使用线程池。

AsyncTask是一个抽象的泛型类,它提供了Params、Progress和Result这三个泛型参数,其中Params表示参数的类型,Progress表示后台任务的执行进度的类型,而Result则表示后台任务的返回结果的类型,如果AsyncTask确实不需要传递具体的参数,那么这三个泛型参数可以用Void来代替。AsyncTask这个类的声明如下所示。

public abstract class AsyncTask<Params,Progress,Result>

AsyncTask提供了4个核心方法,它们的含义如下所示。
(1)onPreExecute(),在主线程中执行,在异步任务执行之前,此方法会被调用,一般可以用于做一些准备工作。
(2)doInBackground(Params...params),在线程池中执行,此方法用于执行异步任务,params参数表示异步任务的输入参数。在此方法中可以通过publishProgress方法来更新任务的进度,publishProgress方法会调用onProgressUpdate方法。另外此方法需要返回计算结果给onPostExecute方法。
(3)onProgressUpdate(Progress...values),在主线程中执行,当后台任务的执行进度发生改变时此方法会被调用。
(4)onPostExecute(Result result),在主线程中执行,在异步任务执行之后,此方法会被调用,其中result参数是后台任务的返回值,即doInBackground的返回值。

上面这几个方法,onPreExecute先执行,接着是doInBackground,最后才是onPostExecute。除了上述四个方法以外,AsyncTask还提供了onCancelled()方法,它同样在主线程中执行,当异步任务被取消时,onCancelled()方法会被调用,这个时候onPostExecute则不会被调用。

当要执行上述下载任务时,可以通过如下方式来完成

new DownloadFilesTask().execute(url1,url2,url3);

AsyncTask在具体的使用过程中也是有一些条件限制的,主要有如下几点:
(1)AsyncTask的类必须在主线程中加载,这就意味着第一次访问AsyncTask必须发生在主线程,当然这个过程在Android 4.1及以上版本中已经被系统自动完成。在Android5.0的源码中,可以查看ActivityThread的main方法,它会调用AsyncTask的init方法,这就满足了AsyncTask的类必须在主线程中进行加载这个条件了。至于为什么必须要满足这个条件,在11.2.2节中会结合AsyncTask的源码再次分析这个问题。
(2)AsyncTask的对象必须在主线程中创建。
(3)execute方法必须在UI线程调用。
(4)不要在程序中直接调用onPreExecute()、onPostExecute、doInBackground和onProgressUpdate方法。
(5)一个AsyncTask对象只能执行一次,即只能调用一次execute方法,否则会报运行时异常。
(6)在Android 1.6之前,AsyncTask是串行执行任务的,Android 1.6的时候AsyncTask开始采用线程池里处理并行任务,但是从Android 3.0开始,为了避免AsyncTask所带来的并发错误,AsyncTask又采用一个线程来串行执行任务。尽管如此,在Android3.0以及后续的版本中,我们仍然可以通过AsyncTask的executeOnExecutor方法来并行地执行任务。

HandlerThread

HandlerThread继承了Thread,它是一种可以使用Handler的Thread,它的实现也很简单,就是在run方法中通过Looper.prepare()来创建消息队列,并通过Looper.loop()来开启消息循环,这样在实际的使用中就允许在HandlerThread中创建Handler了。HandlerThread的run方法如下所示

public void run() {
	mTid = Process.myTid();
	Looper.prepare();
	synchronized (this) {
		mLooper = Looper.myLooper();
		notifyAll();
	}
	Process.setThreadPriority(mPriority);
	onLooperPrepared();
	Looper.loop();
	mTid = -1;
}

从HandlerThread的实现来看,它和普通的Thread有显著的不同之处。普通Thread主要用于在run方法中执行一个耗时任务,而HandlerThread在内部创建了消息队列,外界需要通过Handler的消息方式来通知HandlerThread执行一个具体的任务。HandlerThread是一个很有用的类,它在Android中的一个具体的使用场景是IntentService。由于HandlerThread的run方法是一个无限循环,因此当明确不需要再使用HandlerThread时,可以通过它的quit或者quitSafely方法来终止线程的执行,这是一个良好的编程习惯。

IntentService

IntentService是一种特殊的Service,它继承了Service并且它是一个抽象类,因此必须创建它的子类才能使用IntentService。IntentService可用于执行后台耗时的任务,当任务执行后它会自动停止,同时由于IntentService是服务的原因,这导致它的优先级比单纯的线程要高很多,IntentService封装了HandlerThread和Handler,这一点可以从它的onCreate方法中看出来,如下所示

public void onCreate() {
	// TODO: It would be nice to have an option to hold a partial wakelock
	// during processing,and to have a static startService(Context,Intent)
	// method that would launch the service & hand off a wakelock.
	super.onCreate();
	HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
	thread.start();
	mServiceLooper = thread.getLooper();
	mServiceHandler = new ServiceHandler(mServiceLooper);
}

IntentService是继承并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统的Service一样,同时,当任务执行完后,IntentService会自动停止,而不需要我们手动去控制或stopSelf()。另外,可以启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。

IntentServic示例

public class MIntentService extends IntentService {

    public MIntentService(){
        super("MIntentService");
    }

    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     * @param name Used to name the worker thread, important only for debugging.
     */
    public MIntentService(String name) {
        super(name);
    }

    @Override
    public void onCreate() {
        Log.e("MIntentService--", "onCreate");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e("MIntentService--", "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.e("MIntentService--", Thread.currentThread().getName() + "--" + intent.getStringExtra("info") );
        for(int i = 0; i < 100; i++){ //耗时操作
            Log.i("onHandleIntent--",  i + "--" + Thread.currentThread().getName());
        }
    }

    @Override
    public void onDestroy() {
        Log.e("MIntentService--", "onDestroy");
        super.onDestroy();
    }
}

IntentService总结

  1. 子类需继承IntentService并且实现里面的onHandlerIntent抽象方法来处理intent类型的任务请求。
  2. 子类需要重写默认的构造方法,且在构造方法中调用父类带参数的构造方法。
  3. IntentService类内部利用HandlerThread+Handler构建了一个带有消息循环处理机制的后台工作线程,客户端只需调用Content#startService(Intent)将Intent任务请求放入后台工作队列中,且客户端无需关注服务是否结束,非常适合一次性的后台任务。比如浏览器下载文件,退出当前浏览器之后,下载任务依然存在后台,直到下载文件结束,服务自动销毁。
  4. 只要当前IntentService服务没有被销毁,客户端就可以同时投放多个Intent异步任务请求,IntentService服务端这边是顺序执行当前后台工作队列中的Intent请求的,也就是每一时刻只能执行一个Intent请求,直到该Intent处理结束才处理下一个Intent。因为IntentService类内部利用HandlerThread+Handler构建的是一个单线程来处理异步任务。
Android NDK C++中的多线程 Android NDK C++中的多线程 前言 我们都知道Android是基于Linux内核的,而Linux是遵循POSIX线程标准的,POSIX线程库中有 一系列Pthreads API方便我们对Linux线程的操作。所以我们在Android中使用C/C++线程也就转到 了使用POSIX线程库。他们都在头文件“pthread.h”中。 函数相关 1、pthread_t: 用于声明... 阅读详情

相关推荐

Android开发中的线程池使用

Android 线程池的使用 ThreadPoolExecutor

u012514113的专栏 3512

Android的线程和线程池

从用途上来说Android的线程主要分为主线程和子线程两类,主线程主要处理和界面相关的工作,子线程主要处理耗时操作。除Thread之外,Android中还有其他扮演线程的角色如AsyncTask、IntentService、HandleThread,其中AsyncTask的底层用到了线程池,IntentService和HandleThread的底层直接使用了线程。AsyncTask内部封装了线程池和Handler主要是为了方便开发者在在线程中更新UI;

Android 开发架构 695

Android中的线程和线程池的使用及封装使用总结

相关线程知识先扩充一下: 主线程和子线程 主线程(也叫UI线程):在java中默认情况下一个进程只有一个线程,这个线程就是主线程。其主要作用是处理和界面交互相关的逻辑,主线程不能做太多耗时的操作,否则会产生界面卡顿的感觉。为保持较快的响应速度,子线程就出场了。 子线程:也叫工作线程,除了主线程之外的都是子线程。 基本用途:主线程是运行四大组件及处理它们和用户的交互,子线程处理耗时的任务,如......

小羊子的技术专栏 7721

全面详解Android实现多线程的几种方式(史上最全,最详细)

一、前言 Android多线程实现方式包括: 1、基础使用 继承Thread类 实现Runnable接口 Handler 2、复合使用 AsyncTask HandlerThread IntentService 3、高级使用 线程池(ThreadPool) 接下来对这几种实现多线程的方式进行全面 讲解。 二、基础使用 Android多线程实现的基础使用包括: 继承Thread类 实现Runnable接口 Handler 接下来对各个进行分析。 1、继承Thread类 1.1 简介

u013773608的博客 2万+

AI人工智能全模态大模型架构:推动智能交通发展的架构设计

本文旨在阐述全模态大模型在智能交通领域的架构设计原理和应用方法。我们将探讨如何利用多模态AI技术解决交通流量预测、事故预警、路线优化等关键问题。文章将从基础概念入手,逐步深入技术细节,最后探讨实际应用和未来发展方向。全模态大模型:能够处理和理解多种数据模态(如图像、文本、语音等)的大型AI模型智能交通系统(ITS):利用先进技术优化交通流量和安全性的综合系统多模态融合:将不同数据源的信息整合处理的技术核心概念回顾全模态大模型是能够处理多种数据类型的强大AI系统。

AGI×大数据,开启智能时代的认知跃迁;解码AGI,赋能数据驱动的智能革命。 835

PLL锁相环性能上不去?可能是电荷泵的电流失配在捣鬼(附Jae-Shin Lee经典方案解析)

本文深入分析了PLL锁相环性能瓶颈的根源——电荷泵电流失配问题,详细解析了Current Mismatch和Current Deviation的区别及其对系统的影响。重点介绍了Jae-Shin Lee的多级电流镜技术,该方案通过运放构建虚拟短路和四级电流镜结构,显著降低了电流失配,使参考杂散改善15dB以上。文章还提供了从仿真到流片的完整优化流程,帮助工程师系统解决电荷泵性能问题。

weixin_30684743的博客 371

Android之 线程详解

线程详解

qq_29848853的博客 3355

科研党必备:5个高效查找论文开源代码的宝藏网站(附实战技巧)

本文为科研工作者推荐5个高效查找论文开源代码的宝藏网站,包括ResearchCode和PapersWithCode等工具,提供实战技巧如进阶搜索语法和代码质量评估体系,帮助快速定位高质量实现并提升复现效率。特别分享隐藏代码库的检索方法和智能工作流配置,助力科研党高效完成论文复现。

weixin_28829629的博客 402

带你深入了解Android线程

线程的合理使用可以提高应用的性能和用户体验。在本文中,我将详细介绍 Android 线程的概念、线程的创建和管理、线程间的通信以及常见的线程相关的类和接口。线程是操作系统中独立执行的最小单元,它负责执行程序中的指令。在 Android 中,应用程序运行在主线程(也称为 UI 线程)上,主线程负责处理用户界面的更新和事件响应。为了避免主线程被耗时的操作阻塞,Android 提供了多线程编程的支持,允许开发者创建和管理其他线程来执行耗时任务。线程的合理使用对于提升应用的性能和用户体验非常重要。

Dakaring的专栏 2018

ESP32-S3开发环境避坑指南:VS Code+ESP-IDF离线安装全流程(附国内镜像加速)

本文提供了一份详细的ESP32-S3开发环境离线安装指南,重点解决网络依赖问题。通过整合国内镜像加速,手把手教你完成VS Code、ESP-IDF框架、工具链及Python依赖的本地化部署,实现稳定、可重复的开发环境搭建,大幅提升IoT开发效率。

peach的博客 962

【BLE系列-第六篇】GATT解析:属性、特征、描述符的逻辑关系

本文系统介绍了BLE协议中的ATT和GATT机制。ATT以"属性"为基本数据单元,包含UUID、Handle、权限和Value四个要素。GATT则在ATT基础上构建了服务、特征和描述符的层次结构:服务(UUID:0x2800/0x2801)通过声明属性标识,特征声明(UUID:0x2803)指向特征值(UUID:0x2Axx或自定义),描述符(UUID:0x2900~0x290F)提供附加信息。GATT复用ATT发现机制,通过定义特定UUID语义实现服务发现和特征管理。这种设计使BLE设

qq_43399763的博客 1929

Android 源码分析(三)安卓中的线程

上一节我们一起探索了 Handler 的跨线程通信机制,这里我么趁热打铁,一举拿下 Android 中的线程。 今天我们主要探索 AsyncTask、HandlerThread、IntentService 三个类,这三个类的表现形式和传统线程有一定的区别,但是本质还是基于线程做的处理。 本文将会涉及很多 hadnler 的知识点,建议学习本文的小伙伴先学习上一章 Android 源码分析(二)ha...

weixin_33895657的博客 151

AD17入门简单教程(一)

AD17入门简单教程 我写这篇文章主要是因为最近刚学习完了AD17,想做一下总结,也希望通过自己心得的帮助一些刚入门AD17的小白。 总结一共分为两大部分,包括AD17的下载安装与汉化(文末有详细链接)、工程的创建、元器件库、PCB、走线中的常用命令介绍,文末还附有完整的PCB工程以及讲解视频。 第一部分工程的创建及元器件库常用命令 1.首先在桌面上创建一个文件夹,然后在AD17点击左上角的文件中...

qq_45433195的博客 2万+

Android Framework中的线程Thread及它的threadLoop方法

当初跟踪Camera的代码中的时候一直追到了HAL层,而在Framework中的代码看见了若干个Thread。它们普遍的特点就是有一个threadLoop方法。按照字面的意思应该是这个线程能够循环处理数据。对应我想到到了java上层中的HandlerThread,这个估计也差不多,但当时心里总有一个疙瘩,想弄清楚它到底是怎么循环起来的。Android中java世界的Thread先来看看java是怎么

frank 的专栏 3万+

NHANES数据库实战:数据合并与加权分析技巧

本文详细解析了NHANES数据库实战中的核心技巧,重点阐述了数据合并与加权分析的正确方法。通过两个具体案例,手把手指导如何从数据下载、合并、权重计算到使用R语言survey包进行加权统计分析,避免因忽略复杂抽样设计而导致的研究偏倚,确保分析结果的准确性与可发表性。

weixin_29057065的博客 585

[RAM] DRAM 导论:DDR4 | DDR5 | LPDDR5 | GDRR6 | HBM 应运而生

有数据的地方就有存储, 内存是谁都离不开的产品。而动态随机存取存储器(DRAM)作为一种常见的内存。本博客将介绍DRAM的基本概念、工作原理、优缺点以及应用领域等方面。

串起点滴 3918

Android中的线程通信

准备知识 为什么要学习ThreadLocal呢? 因为这个类是线程中存储数据的类,在Android处理消息的过程中,它其中存储了主线程的Looper,而Looper中又创建了MessageQueue。在App启动的过程中,主线程把Looper放入ThreadLocal中,在处理消息的过程中,子线程通过myLooper()方法获取到主线程中的Looper和MessageQueue,从而把主线程和子线...

kimlllll的博客 183

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

安卓中的子线程卡死问题

        通常大家知道,在安卓主线程中不能进行太多的耗时操作,即使是初始化过程,也会在代码开头统一完成,耗时操作一般会交给安卓中的子线程完成,然而子线程也不是无所不能的强大,里面的操作过多,也会卡死,这时有2个解决方案,一是在子线程中再开一个子线程,循环嵌套。二是利用handle-thread机制,尽量把耗时的操作转移一部分到handlez消息出来机制中去。因为handle是顺序执行的,为此...

风之云的博客 3134

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Android中的线程和线程池

一、Android中的线程 1.Android中的线程形态主要有三种,分别是AsyncTask、HandlerThread以及intentService。关于AsyncTask在上篇文章已经对他进行了详细的描述,这里就不再展开。详情可点击AsyncTask异步任务总结。 2.HandlerThread就是一种可以使用Handler的Thread,,它继承了Thread,它的实现就是在r

sinat_21112393的博客 769

安卓中的线程

应用启动时,系统会为应用创建一个名为“主线程”的执行线程。 此线程非常重要,因为它负责将事件分派给相应的用户界面小部件,其中包括绘图事件。 此外,它也是应用与 Android UI 工具包组件(来自 android.widget)和 android.view 软件包的组件)进行交互的线程。因此,主线程有时也称为 UI 线程。系统不会为每个组件实例创建单独的线程。运行于同一进程的所有组件均在 UI 线

huboemail的博客 257

android线程池简书,Android中的线程池总结篇

一:什么是线程池?线程池顾名思义就是事先创建若干个可执行的线程放入一个池(容器)中,需要的时候从池中获取线程不用自行创建,使用完毕不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开销。二:线程池的优点1.重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销。2.能有效控制线程池的最大并发数,避免大量的线程之间因为互相抢占系统资源而导致的阻塞现象。3.能够对线程进行简单的管理,并提供...

weixin_39630771的博客 220

Android中的UI线程详解

本文主要讲述了什么是UI线程,为什么会出现ANR,为什么不能在UI线程之外更新UI,以及如何在在线程中更新UI。

在地图上飞行 2002
上一篇: C++面试题&知识点整理
下一篇: 面试经验
augfun
博客等级 码龄10年 311粉丝 662原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值