在代码中使用多线程技术

线程基础

可以把线程想象成单一顺序的指令集。这些指令集 被翻译并交给设备的硬件来执行。
多个指令集被同事执行时,这样的环境被称为多线程。多线程对提升任何系统的运行速度都有帮助。因为并行总是快于串行。此外对于有用户接口的程序,不仅可以提高程序的相应速度,通常也能更好的资源和系统管理。

多核cpu

知道几年前,处理器同一时刻只能执行一个命令。尽管多线程的框架已经存在。多线程中的代码使用Cpu时间片的技术顺序执行。所以并不是真正的多线程。这种情况下,我们并不清楚虚拟机会按照怎么航的顺序执行多线程的代码。然而多核cpu技术存在多年,可以同事执行多个代码,实现真正的多线程。

线程

要创建一个线程,需要使用Thread对象,调用Thread.start() 方法来启动它,让他与当前线程并发执行。于是虚拟机受到指令,就会创建一个新线程,并执行Thread.run() 方法中相关的字节码。将代码添加到线程中执行有两种方式:

  • 继承自Thread类:创建一个继承自Thread的类,接着,你需要覆盖Thread.run() 方法,指定当前Thread.start() 方法被调用时要执行的内容。
  • 实现Runable 接口:通过这种方式,当Thead.start() 方法被调用的时候,Runnable.run()方法中的代码就会执行。
    一个线程总是由另外一个线程启动,所以总有一个特殊的线程,是第一个启动的线程。这个应用程序一启动就创建并执行的第一个线程,叫做主线程。
    java为线程提供了一个优先级系统,这意味着可以改变某个线程的优先级,让他相对于其他线程更快或者更慢的执行。
    和优先级有关的属性如下:
/**
 * 线程的优先级属性
 */
private int priority;
/**
 * 线程所能拥有的最大优先级.
 */
public final static int MIN_PRIORITY = 1;

/**
 * 线程默认的优先级.
 */
public final static int NORM_PRIORITY = 5;

/**
 * 线程所能拥有的最大优先级.
 */
public final static int MAX_PRIORITY = 10;

多线程特点:

多线程在应用程序汇总的执行顺序是不可预期的。不能保证那个线程被优先执行,或那个会先执行完成。而且这里所指的不仅是某块代码,甚至精确到某行代码。在一些特殊情况下,当需要按照某个特定顺序访问某个对象时,多线程的执行结果令人担忧。因此要让对象按照正确的顺序被访问,且同一时间内只能被同一个线程访问。换句话说,当一个对象被另外线程访问时候,要阻止其他线程对它进行访问。

线程安全

线程安全指的是代码的安全执行,共享的数据,不能并发的被修改。显而易见,访问一个只读对象,永远不会有安全问题。但可写对象,就可能存在问题。如果一个多线程应用程序在共享对象上没有并发操作,那么他就是线程安全的。
让我们看看这在java框架中意味着什么。java使用一个名为监视器(monitor)的概念。每个对象都有一个监视器。每个对象都有一个监视器。监视器确保同一个时刻一个对象只会被锁住一次。其他任何的锁定意图都会被放进队列中。
java通过一个关键字做这些和锁定相关的事情。Synchronized。 该关键字可以:

  • 作为一个声明使用
  • 也可以声明一个Synchronized方法
    当两个或者更多的线程出现相互等待的情况,那么这些线程就永远被锁住了。

Android中的线程类型

有三类:

  • 对应java中的主线程,Android中的主线程,又叫UI线程
  • 从主线程启动新线程进行后台操作,为应用程序创建的其他线程,都被称作:后台线程(Background Thread)或者Worker Thread
  • Binder线程,用于进程间通信

1) 主线程

主线程是唯一一个可以管理用户界面的线程,明白这点很关键。这也是为什么被称为UI线程。UI线程的生命周期和应用程序一样长,和程序进程一样长。因为应用程序需要这样一个线程,以保证应用程序在任何时候都能与应用程序进行交互。Android的UI不是线程安全的,如果View能被不同的线程所访问或修改,想象画面就很美——完全乱了套了。
另外也是为了加快UI,因为加锁和解锁操作消耗太大。

2)工作线程

Android的UI线程,可以处理一些非UI的操作,但金陵不要这么做。应该让主线程只处理UI相关的操作,任何耗时操作都必须放在非UI线程中完成。以保证应用程序的流畅度,带来良好的用户体验,者也是工作线程的主要目的。工作线程用来执行那些坑内会影响UI的耗时操作。更糟糕的是,如果在UI线程中进行这些操作,很可能会卡主UI,知道执行结束。这会引发我们熟悉的ANR异常。

Android中的线程框架

1)handler

(未完成,等待补充)

2) HandlerThread

他是一个非常有用的Thead子类,糅合了Thread和Handler。

1>与传统线程不一样,HandlerThread是可以被 重用的

他一直处于活跃状态,直到HandlerThread.quit()方法被调用。这个特殊的方法能终止looper,任何之后发送的Message或者Runnable都会失败,并且MessageQueue会被清空。该方法会强制等待中的Message和Runnable退出,他们不会被分发到Handler。为了确保没有等待中的消磁会被终止或分发,可以使用HandlerThread.quitSafely()方法。但是无论哪个方法被调用,HandlerThread对象都不能再被使用,就像Thread已经执行结束了一样

2> 当我们需要一个可供一直使用的线程时,HandlerThread是一个不错的选择。
3> 当不在使用时候,记得退出以释放资源

处理多线程和线程间通信时,使用HandlerThread对Looper进行管理,是一个不错的选择。他还可以被多个Message和Runnable重用。但要记住,当不在使用时候,记得退出以释放资源

3)AsyncTask

内部含有四个需要重载的方法,doInBackGround()方法是抽象的,并且执行在工作线程中。

  • onPreExecute() 在启动后台线程之前被调用,可用于告知用户:“后台在处理一些事情”
  • onProgressUpdate() 当工作线程中的进度有变化时,可在此方法中对UI进行更新
  • onPostExecute() 该方法用于处理从工作线程返回的结果
  • onCancelled() 当AsyncTask在UI线程中被取消的时,可通过该方法处理一些事务。
    (未完成,有待添加)
使用技巧总结
  • AsyncTask的目的是让工作线程能与UI线程通信。那么,如果我们的后台操作不需要通知用户,或者说,不需要更新UI,也就没必要使用AsyncTask。一个Thread就够了,并且性能比Thread好。
  • AsyncTask在Activity以内部类的形式多次使用,存在内存泄露的风险。

4) Loader

Loader能对AsyncTask进行有效的替换,并弥补了他的部分不足。
loader非常适合异步操作,比如,从远程服务器检索数据。当新数据可用时,他们能触发回调,通知调用者。调用者肯能是Activity或者Fragment. Loader是声明周期独立的,他与Activity的Fragment的生命周期变化无关系。他仍然在后台进行操作。并且会通知最新创建的Activity和Fragment实例。中间还存在缓存机制,可以放心使用。
Loader使用的应用上下文,无Activity泄漏风险

LoaderManager
  • 每个Activity或Fragment有且只有一个LoaderManager.
  • 在Activity和Fragment中,通过getLoaderManager()方法获得
  • LoaderManger能对loader进行操作
使用技巧

在使用loader的时候我们通常要使用:

  • CursorLoader或者AsyncTaskLoader这样的包装过的类
  • 或者创建一个Loader的子类
总结:
  • 无泄漏风险
  • 为用户缓存数据
    Loader框架改进了AsyncTask的特性,让用户不用担心Activity或者Fragment的生命周期,并且为用户缓存数据。因此它是AsyncTask的一个有效替代品。
  • 使用更简单方便
    使用和管理Loader 更加容易。

5)Service

  • Service没有UI要处理
  • 他的主要目的,是在后台执行长时间的操作
    想想我们前面看到的各种 线程,在大部分情况下,使用它们是为了Activity 的生命周期内对UI更新。但Service不同,他是一个不受任何限制,独立运行在后台的对象。
  • service 不需要与用户交互,也不需要用户界面。
  • 因此大部分不需要和用户交互的操作,都可以放到Service中进行。

有两种类型的Service.

  • Started Service
  • Bound Service
    (未完成,后面补充)

6)IntentService

IntentSevice 是平台提供的一个队Service的特殊实现。他在某些情况下非常有用。IntentService包装了一个单独的后台线程,来执行不同的请求,这些请求与Intent有关,传入的Intent 被放置在一个队列中,依次执行。当队列变空的时,IntentService会自动销毁。因此,他的生命周期与Service不同。只有当后台线程还在执行操作的时,它才是活跃的状态。

使用技巧
  • 当你需要在一个单独线程中,顺序的执行一系列后台操作的时,IntentService是一个正确的选择
  • 你不需要处理Service的生命周期(他提供了异步操作所需的一切,并且不会影响UI)

二 进程间通信

1) 远程过程调用(Rpc)

2) AIDL技术

3)Messager

4) ContentProvider异步技术

5)BroadcastReceiver异步技术

它有一个异常短暂的生命周期。所以并不能执行长时间运行的操作。然而broadcastReceiver非常适合于启动一个后台线程,例如IntentService 。

三. 重复性任务

Timer

ScheduledExecutorService

AlarmManager

7)多线程调试

StrictMode 等

参考文献:
《Android 高性能变编程》【西班牙】Enrique López Mañas(恩里克·洛佩斯·马尼亚斯),【意】Diego Grancini (迪戈·格兰奇尼)著叶坤 译

《Kotlin实战》【俄】Dmitry Jemerov Svetlana Isakova 著 覃宇 罗丽 李思阳 蒋扬海 译
《重构改善既有代码设计》【美】马丁福勒(MartinFowler)著 熊节 林从羽译
Android app性能调优

安卓包的优化
内存占用优化
app渲染优化
掌握多线程使用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,135评论 6 514
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,317评论 3 397
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,596评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,481评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,492评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,153评论 1 309
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,737评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,657评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,193评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,276评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,420评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,093评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,783评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,262评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,390评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,787评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,427评论 2 359

推荐阅读更多精彩内容