文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android中的线程和线程池有什么作用

2023-07-04 19:59

关注

今天小编给大家分享一下Android中的线程和线程池有什么作用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

前言

从用途上来说Android的线程主要分为主线程和子线程两类,主线程主要处理和界面相关的工作,子线程主要处理耗时操作。除Thread之外,Android中还有其他扮演线程的角色如AsyncTask、IntentService、HandleThread,其中AsyncTask的底层用到了线程池,IntentService和HandleThread的底层直接使用了线程。

AsyncTask内部封装了线程池和Handler主要是为了方便开发者在在线程中更新UI;HandlerThread是一个具有消息循环的线程,它的内部可以使用Handler;IntentService是一个服务,系统对其进行了封装使其可以更方便的执行后台任务,IntentService内部采用HandleThread来执行任务,当任务执行完毕后IntentService会自动退出。IntentService是一个服务但是它不容易被系统杀死因此它可以尽量的保证任务的执行。

1.主线程和子线程

主线程是指进程所拥有的的线程,在Java中默认情况下一个进程只能有一个线程,这个线程就是主线程。主线程主要处理界面交互的相关逻辑,因为界面随时都有可能更新因此在主线程不能做耗时操作,否则界面就会出现卡顿的现象。主线程之外的线程都是子线程,也叫做工作线程。

Android沿用了Java的线程模型,也有主线程和子线程之分,主线程主要工作是运行四大组件及处理他们和用户的交互,子线程的主要工作就是处理耗时任务,例如网络请求,I/O操作等。Android3.0开始系统要求网络访问必须在子线程中进行否则就会报错,NetWorkOnMainThreadException

2.Android中的线程形态

2.1 AsyncTask

AsyncTask是一个轻量级的异步任务类,它可以在线程池中执行异步任务然后把执行进度和执行结果传递给主线程并在主线程更新UI。从实现上来说AsyncTask封装了Thread和Handler,通过AsyncTask可以很方便的执行后台任务以及主线程中访问UI,但是AsyncTask不适合处理耗时任务,耗时任务还是要交给线程池执行。

AsyncTask的四个核心类如下:

2.2 AsyncTask的工作原理

2.3 HandleThread

HandleThread继承自Thread,它是一种可以使用Handler的Thread,它的实现在run方法中调用Looper.prepare()来创建消息队列然后通过Looper.loop()来开启消息循环,这样在实际使用中就可以在HandleThread中创建Handler了。

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

HandleThread和Thread的区别是什么?

2.4 IntentService

IntentService继承自Service并且是一个抽象的类因此使用它时就必须创建它的子类,IntentService可用于执行后台耗时的任务,当任务执行完毕后就会自动停止。IntentService是一个服务因此它的优先级要比线程高并且不容易被系统杀死,因此可以利用这个特点执行一些高优先级的后台任务,它的实现主要是HandlerThread和Handler,这点可以从onCreate方法中了解。

//IntentService#onCreate@Overridepublic 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第一次被启动时回调用onCreate方法,在onCreate方法中会创建HandlerThread,然后使用它的Looper创建一个Handler对象ServiceHandler,这样通过mServiceHandler把消息发送到HandlerThread中执行。每次启动IntentService都会调用onStartCommand,IntentService在onStartCommand中会处理每个后台任务的Intent。

//IntentService#onStartCommand@Overridepublic int onStartCommand(@Nullable Intent intent, int flags, int startId) {    onStart(intent, startId);    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;}//IntentService#onStart@Overridepublic void onStart(@Nullable Intent intent, int startId) {    Message msg = mServiceHandler.obtainMessage();    msg.arg1 = startId;    msg.obj = intent;    mServiceHandler.sendMessage(msg);}private final class ServiceHandler extends Handler {    public ServiceHandler(Looper looper) {        super(looper);    }    @Override    public void handleMessage(Message msg) {        onHandleIntent((Intent)msg.obj);        stopSelf(msg.arg1);    }}

onStartCommand是如何处理外界的Intent的?

在onStartCommand方法中进入了onStart方法,在这个方法中IntentService通过mserviceHandler发送了一条消息,然后这个消息会在HandlerThread中被处理。mServiceHandler接收到消息后会把intent传递给onHandlerIntent(),这个intent跟启动IntentService时的startService中的intent是一样的,因此可以通过这个intent解析出启动IntentService传递的参数是什么然后通过这些参数就可以区分具体的后台任务,这样onHandleIntent就可以对不同的后台任务做处理了。当onHandleIntent方法执行结束后IntentService就会通过stopSelf(int startId)方法来尝试停止服务,这里不用stopSelf()的原因是因为这个方法被调用之后会立即停止服务但是这个时候可能还有其他消息未处理完毕,而采用stopSelf(int startId)方法则会等待所有消息都处理完毕后才会终止服务。调用stopSelf(int startId)终止服务时会根据startId判断最近启动的服务的startId是否相等,相等则立即终止服务否则不终止服务。

每执行一个后台任务就会启动一次intentService,而IntentService内部则通过消息的方式向HandlerThread请求执行任务,Handler中的Looper是顺序处理消息的,这就意味着IntentService也是顺序执行后台任务的,当有多个后台任务同时存在时这些后台任务会按照外界发起的顺序排队执行。

3.Android中的线程池

线程池的优点:

Android的线程池的概念来自于Java中的Executor,Executor是一个接口,真正的线程的实现是ThreadPoolExecutor,它提供了一些列参数来配置线程池,通过不同的参数可以创建不同的线程池。

3.1 ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,                          int maximumPoolSize,                          long keepAliveTime,                          TimeUnit unit,                          BlockingQueue<Runnable> workQueue,                          ThreadFactory threadFactory,                          RejectedExecutionHandler handler) {    if (corePoolSize < 0 ||        maximumPoolSize <= 0 ||        maximumPoolSize < corePoolSize ||        keepAliveTime < 0)        throw new IllegalArgumentException();    if (workQueue == null || threadFactory == null || handler == null)        throw new NullPointerException();    this.corePoolSize = corePoolSize;    this.maximumPoolSize = maximumPoolSize;    this.workQueue = workQueue;    this.keepAliveTime = unit.toNanos(keepAliveTime);    this.threadFactory = threadFactory;    this.handler = handler;}

ThreadPoolExecutor是线程池的真正实现,它的构造函数中提供了一系列参数,先看一下每个参数的含义:

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

3.2线程池的分类

以上就是“Android中的线程和线程池有什么作用”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯