HandlerThread详解「建议收藏」

HandlerThread详解「建议收藏」转载请注明链接:HandlerThread版本:2018/9/9-1(10:10)HandlerThread问题汇总基本使用(7)源码(7)问题汇总【☆】是补充问题,直接给答案。其余问题答案都在文中。HandlerThread是什么?【☆】HandlerThread任务是并行处理的?不是!是串行处理的。如果一个任务执行…

大家好,又见面了,我是你们的朋友全栈君。

转载请注明链接:https://blog.csdn.net/feather_wch/article/details/82556153

HandlerThread

版本:2018/9/9-1(10:10)


问题汇总

  1. 总结HandlerThread相关所有可能的问题,用于自我检测和查漏补缺。
  2. 【☆】标记的是补充问题,直接给答案。其余问题答案都在文中。

  1. HandlerThread是什么?
  2. 【☆】HandlerThread任务是并行处理的?

    不是!是串行处理的。如果一个任务执行时间过长会阻塞后续任务。

  3. 【☆】HandlerThread不能执行耗时过长的任务?

    内部任务是串行处理的。如果一个任务执行时间过长会阻塞后续任务。

  4. 【☆】如何通过HandlerThread来执行一个具体任务?

    外界需要通过Hanlder的消息方式来通知HandlerThread来执行一个具体任务

  5. HandlerThread产生的背景?

  6. HandlerThread如何退出?
  7. HandlerThread的典型使用场景?
  8. HandlerThread的基本使用流程?
  9. HandlerThread是如何做到一个线程能够一直运行,有新的任务就处理,没有任务就等待?
  10. handlerThread.getLooper()必须在handlerThread.start()之后调用?
  11. HandlerThread的构造方法
  12. HandlerThread的run()做了哪些事情?
  13. HandlerThread如何退出?quit/quit或quitSafely
  14. HandlerThread的Tid有什么用?
  15. 为什么run中有notifyAll,getLooper中有wait?
  16. 为什么要设置线程优先级?为什么能防止内存泄漏和解决数据安全问题?
  17. 线程优先级设置的两种方法?两种方式的优先级范围?

基本使用(7)

1、HandlerThread是什么?

  1. 内嵌Looper、Handler、MessageQueue的Thread
  2. 内部具有队列,任务会串行处理。(如果一个任务执行时间过长,会阻塞后续任务)
  3. 执行任务:外界需要通过Hanlder的消息方式来通知HandlerThread来执行一个具体任务

2、HandlerThread产生的背景?

  1. 一般线程执行完任务后就会停止,如果有很多任务导致频繁创建和销毁线程,会损耗系统资源。
  2. 如果子线程需要更新UI,要使用到Handler,此外需要创建Looper等操作,比较繁琐。

3、HandlerThread如何退出?

  1. HandlerThread的run方法是无限循环执行的,需要通过HandlerThread的quit或quitSafely方法来终止线程的执行

4、HandlerThread的典型使用场景?

  1. HandlerThread典型使用场景是IntentService

5、HandlerThread的基本使用

/**============================= * 创建并开启HandlerThread *==============================*/
        //创建一个线程,线程名字:handler-thread
        HandlerThread mHandlerThread = new HandlerThread( "handler-thread") ;
        //开启一个线程
        mHandlerThread.start();
/**=========================== * 创建Handler并实现具体任务 *============================*/
        //在这个线程中创建一个handler对象
        Handler handler = new Handler( mHandlerThread.getLooper() ){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                //这个方法是运行在 handler-thread 线程中的 ,可以执行耗时操作
                Log.d( "handler " , "消息: " + msg.what + " 线程: " + Thread.currentThread().getName()  ) ;
            }
        };
/**=========================== * 开启任务的执行 *=============================*/
        //在主线程给handler发送消息
        handler.sendEmptyMessage(1) ;

6、HandlerThread是如何做到一个线程能够一直运行,有新的任务就处理,没有任务就等待?

  1. 利用了Looper.loop()进行无限循环。

7、handlerThread.getLooper()必须在handlerThread.start()之后调用

  1. 不然因为isAlive() = true,会导致直接返回null。无法去构造Handler
Handler handler = new Handler(handlerThread.getLooper());
// java.lang.NullPointerException: Attempt to read from field 'android.os.MessageQueue android.os.Looper.mQueue' on a null object reference

源码(7)

1、HandlerThread的构造方法

  1. 默认的线程优先级为:THREAD_PRIORITY_DEFAULT,标准的app线程优先级
  2. 可以自定义线程优先级
        // HandlerThread.java
        public HandlerThread(String name) {
            super(name);
            mPriority = Process.THREAD_PRIORITY_DEFAULT;
        }
        public HandlerThread(String name, int priority) {
            super(name);
            mPriority = priority;
        }

2、HandlerThread的run()

  1. 获取Tid,设置优先级,创建Looper
  2. 回调 onLooperPrepared(),并开启loop()
  3. getLooper()获取Looper时,会阻塞调用者线程,直到HandlerThread创建了Looper。
        // HandlerThread.java-线程的run方法
        @Override
        public void run() {
            // 1、获取到Tid
            mTid = Process.myTid();
            // 2、创建Looper、MessageQueue
            Looper.prepare();
            synchronized (this) {
                // 3、存储,并唤醒从HandlerThread.getLooper()方法而阻塞的线程
                mLooper = Looper.myLooper();
                notifyAll();
            }
            // 4、设置线程优先级
            Process.setThreadPriority(mPriority);
            // 5、回调,进行loop前的准备工作。
            onLooperPrepared();
            // 6、开始loop()
            Looper.loop();
            mTid = -1;
        }
        // HandlerThread.java-loop()前的准备工作
        protected void onLooperPrepared() {
        }

        // HandlerThread.java-获取到该线程的Looper
        public Looper getLooper() {
            // 1、不存活,直接返回null
            if (!isAlive()) {
                return null;
            }
            // 2、在looper创建前,处于阻塞状态。
            synchronized (this) {
                while (isAlive() && mLooper == null) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                }
            }
            return mLooper;
        }

        //@hide: 获取Handler或者用调用者线程的looper创建Handler
        public Handler getThreadHandler() {
            if (mHandler == null) {
                mHandler = new Handler(getLooper());
            }
            return mHandler;
        }

3、HandlerThread如何退出?quit/quit或quitSafely

  1. 调用Looper的退出方法。
        // 通过Looper的quit和quitSafely进行退出。
        public boolean quit() {}
        public boolean quitSafely() {}

4、HandlerThread的Tid有什么用?

  1. Thread id,就是线程的ID,表明线程的身份
// 1、获取到Tid
mTid = Process.myTid();
public int getThreadId() {
  //2、返回Tid
      return mTid;
}

5、为什么run中有notifyAll,getLooper中有wait?

  1. 避免线程同步问题导致Looper为null
  2. 在getLooper()调用时,可能run()方法中Looper还没有创建成功,此时返回Looper会出现问题。因此需要去wait。
  3. run()中Looper一旦创建好,就可以去notifyAll()让getLooper()可以返回正确的Looper

6、为什么要设置线程优先级?为什么能防止内存泄漏和解决数据安全问题?

  1. 线程优先级主要分为UI线程和后台线程(backgorund)
  2. 线程默认优先级为default,也就是UI线程,会和UI线程去平等的争抢资源。
  3. 在UI性能要求较高的场景下,应该使用后台线程。

7、线程优先级设置的两种方法?两种方式的优先级范围?

1-setThreadPriority()进行设置,线程优先级范围-20~19, 从高优先级~低优先级。

android.os.Process.setThreadPriority (intpriority);
android.os.Process.setThreadPriority (inttid, int priority);
// thread直接设置
Thread a = new MyThread("ThreadA");
a.setOSPriority(Process.THREAD_PRIORITY_LOWEST);// 19
// thread的run方法中进行设置
Thread b = new Thread(new Runnable() {
    @Override
    public void run() {
        Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);
    }
});

2-setPriority()设置,线程优先级范围1~10, 从低优先级~高优先级。

java.lang.Thread.setPriority (int priority);
// setPriority进行设置
Thread a = new MyThread("ThreadA");
a.setPriority(Thread.MAX_PRIORITY);// 10
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/158134.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • IDEA激活成功教程后一直提示JetbrainsAgent 相关的弹框问题

    IDEA激活成功教程后一直提示JetbrainsAgent 相关的弹框问题激活成功教程后打开IDEA就弹框,关闭之后会自动打开浏览器,隔一会也会弹出来 也是一样的问题一开始是说把txt 和 jar 文件放一个路径下之类的方法,几经波折,发现没任何用处~最后各种搜索排查,在设置下更改配置就不弹啦~settings设置下搜索agent 取消”Instrumenting agent(requires debugger restart)”在 Reload classes after compilation:选择第一个 Always…

    2022年8月19日
  • Python源码阅读_python源代码文件

    Python源码阅读_python源代码文件最近想读读Python源码,任何东西学习方法基本都是一样的,先从总体框架进行了解,再从自己侧重的方面逐步深入。1.Python总体架构左边是Python提供的大量的模块、库以及用户自定义的模块。比如在执行importos时,这个os就是Python内建的模块,当然用户还可以通过自定义模块来扩展Python系统。右边是Python的运行时环境,包括对象/类型系统(Object/Type…

    2022年8月23日
  • 三极管的饱和导通条件[通俗易懂]

    三极管的饱和导通条件[通俗易懂]请看图,假设三极管基极电流为1MA,三极管直流放大倍数为50,那么在三极管集电极就有50MA电流。这时如果RL取100Ω,那么在RL两端分得电压5V,而另5V就加在三极管上,这时三极管处于正常放大状态。如果RL取300Ω呢?根据计算。在RL上应该分得15V电压。如果电源电压超过15V,那么这个电路仍处于放大壮态。可这里电源电压只有10V,那么这10V电压几乎全加在了电阻上,而三极管…

    2022年6月29日
  • 论计算机发展史及展望_策略单元培训心得

    论计算机发展史及展望_策略单元培训心得一种对计算机发展史展开研究的策略(3页)本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦!9.9积分一种对计算机发展史展开研究的策略一种对计算机发展史展开研究的策略一种对计算机发展史展开研究的策略一、引言随着中国的开放,科学技术的国际交流日益深入,现代化意义上的计算机产品与技术被不断介绍并引入到国内,且在短时间内取得了迅.L.猛的发展。然而,作为…

    2022年10月18日
  • 云计算(1)—基础知识

    云计算(1)—基础知识一、云计算概述   云计算到底是什么呢?在这个问题上,可谓众说纷纭。比如,在维基百科上的定义是“云计算是一种基于互联网的计算新方式,通过互联网上异构、自治的服务为个人和企业用户提供按需即取的计算”;著名咨询机构Gartner将云计算定义为“云计算是利用互联网技术来将庞大且可伸缩的IT能力集合起来作为服务提供给多个客户的技术”;而IBM则认为“云计算是一种新兴的IT服务交付方式,应用、数据…

    2022年5月15日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号