• Android 多线程、线程池


    1. 多线程

    线程是一种轻量级的执行单元,它可以在应用程序中执行并发任务。

    多线程是指在同一时间内执行多个线程。在Android中,多线程可以帮助我们更好地管理应用程序的资源和响应性能。

    1. 线程池

    线程池是一种用于管理线程的机制,它可以帮助我们更好地管理线程的创建和销毁。线程池可以在需要时创建线程,并在不需要时销毁线程,从而减少了线程创建和销毁的开销。

    1. 项目中典型多线程场景

    主线程

    主线程是UI线程,它负责处理用户界面的事件和更新UI。主线程包括以下任务: 1) 处理用户界面事件:主线程负责处理用户界面事件,例如点击按钮、滚动屏幕等。当用户执行这些操作时,Android系统会将事件发送到主线程,主线程会处理这些事件并更新UI。

    2) 更新UI:主线程负责更新UI,例如更改文本、更改颜色、添加或删除视图等。当我们在代码中更改UI时,这些更改都必须在主线程中执行。

    3) 处理生命周期事件:主线程负责处理Activity和Fragment的生命周期事件,例如创建、启动、暂停、恢复和销毁。这些事件都必须在主线程中执行。

    4) 处理广播事件:主线程负责处理广播事件,例如网络状态变化、电池电量变化等。当这些事件发生时,Android系统会将它们发送到主线程,主线程会处理这些事件并执行相应的操作。

    5) 处理异步任务:主线程负责处理异步任务的结果。当我们执行异步任务时,任务的结果会在主线程中返回,并在主线程中处理。 需要注意的是,如果我们在主线程中执行耗时操作,例如网络请求或数据库查询,会导致UI线程阻塞,从而导致应用程序响应性能下降。因此,我们应该将这些操作放在后台线程中执行,以避免阻塞UI线程

    蓝牙/sensor消息

    接收消息、处理消息在两个线程

    1. 波形绘制

    Retrofit中的线程

    在Retrofit中,我们可以使用Call接口来管理线程。Call接口提供了enqueue()方法来执行异步请求,也提供了execute()方法来执行同步请求。在异步请求中,Retrofit会自动将请求放在一个新的线程中执行,而在同步请求中,请求将在当前线程中执行。如果我们需要在请求中指定线程,可以使用Call接口的enqueue()方法的重载版本,该版本接受一个Callback对象和一个Executor对象作为参数,我们可以在Executor对象中指定线程池来执行请求。

    同步请求execute():

    异步请求:

    RxJava中的线程

    在RxJava中,线程的管理是通过调度器(Scheduler)来实现的。调度器是一个抽象的概念,它定义了任务在哪个线程上执行的规则。RxJava提供了多种不同的调度器,包括: - Schedulers.io():用于执行I/O操作的线程池,适用于网络请求、文件读写等操作。 - Schedulers.computation():用于执行计算密集型操作的线程池,适用于CPU密集型的操作,如图像处理、加密解密等。 - Schedulers.newThread():每次都会创建一个新的线程,适用于需要立即执行的任务。 - AndroidSchedulers.mainThread():用于在Android主线程上执行任务,适用于更新UI等操作。 在RxJava中,我们可以使用subscribeOn()和observeOn()方法来指定任务的执行线程。subscribeOn()方法用于指定任务的订阅线程,而observeOn()方法用于指定任务的观察线程。例如,下面的代码将任务的订阅线程指定为IO线程,观察线程指定为主线程。

    Observable.just("Hello, world!")

    .subscribeOn(Schedulers.io())

    .observeOn(AndroidSchedulers.mainThread())

    .subscribe { text -> textView.text = text }

    这样,当我们订阅这个Observable时,它会在IO线程上执行,然后在主线程上观察结果并更新UI。这种方式可以避免在主线程上执行耗时操作,从而提高应用程序的响应速度和用户体验。

    1. android常见多线程场景、线程的启动和停止

    Thread创建的多个线程

    AsyncTask

    Handler

    ThreadPoolExecutor

    1. 线程安全问题

    • 竞态条件:竞态条件是指多个线程同时访问共享资源,导致结果依赖于线程执行的顺序。这可能会导致不一致的结果或错误的行为。

    • 死锁:死锁是指多个线程互相等待对方释放资源,导致所有线程都无法继续执行。这可能会导致应用程序挂起或崩溃。

    • 活锁:活锁是指多个线程在尝试解决死锁问题时,不断地重试导致无法继续执行。这可能会导致应用程序挂起或崩溃。

    • 内存一致性错误:内存一致性错误是指多个线程同时访问共享内存,导致内存中的数据不一致。这可能会导致不一致的结果或错误的行为。

    措施:

    • 使用同步机制:同步机制可以帮助我们控制多个线程对共享资源的访问。在Java中,我们可以使用synchronized关键字或Lock接口来实现同步。

    • 避免死锁:为了避免死锁,我们可以使用避免策略,例如按照相同的顺序获取锁,或者使用超时机制。

    • 避免活锁:为了避免活锁,我们可以使用随机化策略,例如在等待锁时随机等待一段时间。

    • 使用原子操作:原子操作可以帮助我们避免内存一致性错误。在Java中,我们可以使用Atomic类来实现原子操作。

  • 相关阅读:
    STM32F1网络编程-TCP服务器(基于W5500网卡)
    GB28181 编码规则说明
    博主常用的 idea 插件,建议收藏!!!
    【Django 03】QuerySet 和 Instance应用
    swiper垂直方向全屏实现鼠标滚轮滚动一下切换一屏
    【CSS】笔试题精讲
    和数集团海外团队受邀参加俄罗斯2022区块链峰会
    一款比Typora更简洁优雅的Markdown编辑器神器(完全开源免费)
    计算机三级数据库后台编程技术练习题(一)
    DDoS高防IP到底是什么?
  • 原文地址:https://blog.csdn.net/dream_Insis/article/details/136678036