一、前言
线程(英语:thread)在计算机科学中,是将进程划分为两个或多个线程(实例)或子进程,由单处理器(单线程)或多处理器(多线程)或多核处理系统并发执行。 —— 维基百科
无论在Android还是java开发甚至其他语言开发,大多数都逃不过多线程的话题,当然dart等语言除外(不过也有isolate的概念)。
线程是操作系统CPU资源分配调度的一个单元,在Java中,最常见的就是Thread类,通过该类可以让我们在多线程创建、启动、执行等操作更加得心应手。
二、了解
- 在Thread类中,只有run函数是运行在线程上。
- 通过start()启动线程,实际上会调用native的VMThread.create(this, stackSize)方法创建CPU线程
三、使用方法
1.通过继承Thread启动一个线程
继承Thread,并复写run方法即可
2.通过构造函数传入
直接通过构造函数,传入自定义的Runnable接口
四、详解
1.启动流程
thread.start()是线程启动的入口,只有在start执行时真正创建了native线程,其他准备工作(比如设置name、runnable等)都是在java的当前线程执行处理。
这里Android进行了改造,将start0改成了nativeCreate开启线程。
注意这里做了实例的同步锁。
源码:
2.run流程
主要是执行传入的runnable接口回调。只有在runnable中执行的才是在新线程,其他的都是在当前线程。
由start执行后,由JVM自动调用run方法在新线程中。
源码:
3.wait
wait()为Object的公有方法,使用时需要配合synchronized和Object实例调用,用来阻塞当前线程。此时释放掉synchronized的锁。如果被唤醒也是需要"随机"竞争锁。
- 在哪个线程执行,就会阻塞那个线程
- 必须在synchronized同步代码块中调用
- wait时会释放掉同步锁
- 仅释放调用wait方法的锁,不会改变其他锁的状态
- 会有InterruptedException异常
参数:
- wait():内部调用wait(0),表示无超时时间,一直等待
- wait(long timeout):内部调用wait(timeout, 0)
- wait(long timeout, int nanos):native方法,进入等待状态,如果是0为一直等待,直到收到唤醒通知
举例:
4.notify、notifyAll
notify()、notifyAll()为Object的公有方法,使用时需要配合synchronized和Object实例调用,用来通知唤醒阻塞线程。notify不会有释放锁操作,仅仅通知wait状态的线程可以去竞争锁,而不是立马拿到,需要等到notify代码块执行完毕释放锁。notify为随机唤醒一个阻塞线程,notifyAll为唤醒所有阻塞线程。
- notify操作不会有释放锁操作,仅作为通知
- notify为随机通知一个wait唤起
- notifyAll通知所有wait状态唤起
- 会有InterruptedException异常
举例:
5.sleep
sleep()为Thread的静态方法。使当前线程睡眠指定一段时间,之后自行恢复,notify对此无用。此时会持有thread的lock对象锁,线程休眠也不会释放其他锁。
- 在哪个线程执行,就会阻塞那个线程。
- 睡眠期间不会释放所有锁
- 会有InterruptedException异常
参数:
- sleep(long millis):调用sleep(millis, 0)
- sleep(long millis, int nanos):线程睡眠
案例:
源码:
6.interrupt
interrupt为Thread的公有方法。线程中断后,可通过isInterrupted()进行判断是否处理中断状态。
- 未start()的线程,调用interrupt不影响,后续可正常操作
- 要在中断前执行特殊操作,需要设置 blockedOn(Interruptible b)
- 仅仅是打上中断标志,而非立刻停止。
需要以下做中断try catch,否则造成程序crash。
- Thread.sleep()
- object.wait()
- object.notify()
- object.notifyAll()
- thread.join()
举例:
源码:
7.join
join()是Thread的公有方法,等待线程任务的完成。可重复执行,如果线程销毁了,相当于直接完成。这里会阻塞当前执行线程,对于Android来说,千万不要再主线程去调用防止造成ANR。
参数:
- join():内部调用了join(0),无限制等待。直到任务完成
- join(long millis, int nanos):内部计算处理完具体时间后,调用join(long millis)
- join(long millis):最终调用方法,如果为0,无限时间等待;否则设置对应时间等待,到时自动结束
案例:
源码:
8.yield
让步调度,该线程就会把CPU时间让掉,让其他或者自己的线程执行(也就是谁先抢到谁执行)。同样不会释放锁
五、状态图解
线程状态有5种:
- new: 实例化之后状态,没有start
- runnable:start()之后启动,等待cpu调度执行,非立刻执行
- blocked:阻塞状态,比如等锁
- waiting:无限时间等待状态
- timed_waiting:有限时间等待状态
- terminated:完成或者异常,终止运行
1. 正常线程执行状态:
2. waiting状态线程:
3. blocked状态:
4. timed_waiting状态:
最后
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。

相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
5535

被折叠的 条评论
为什么被折叠?



