乐趣区

你真的了解线程的并发吗

9:10 约会,真爱,请“星标

1、对线程与线程

线程是什么?

是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。线程有就绪、阻塞和运行三种基本状态

多线程:指的是这个程序(一个进程)运行时产生了不止一个线程

并行与并发:先说一下并行:多个 cpu 实例或者多台机器同时执行一段处理逻辑,是真正的同时。并发 通过 cpu 调度算法,让用户看上去同时执行,实际上从 cpu 操作层面不是真正的同时。并发往往在场景中有公用的资源,那么针对这个公用的资源往往产生瓶颈,我们会用 TPS 或者 QPS 来反应这个系统的处理能力。

为啥使用多线程?

总之,为了解决负载均衡问题, 充分利用 CPU 资源. 为了提高 CPU 的使用率, 采用多线程的方式去同时完成几件事情而不互相干扰. 为了处理大量的 IO 操作时或处理的情况需要花费大量的时间等等, 比如: 读写文件, 视频图像的采集, 处理, 显示, 保存等

聊到多线程,多半会聊并发与并行,咋理解并区分这两个的区别呢?

  • 类似单个 CPU,通过 CPU 调度算法等,处理多个任务的能力,叫并发
  • 类似多个 CPU,同时并且处理相同多个任务的能力,叫做并行

在代码中:

并发:不同的代码块交替执行

并行:不同的代码块同时执行

2、线程的运行与创建

2.1 线程的创建

Java 创建线程对象有两种方法:
– 继承 Thread 类创建线程对象
– 实现 Runnable 接口类创建线程对象

新建 MyThread 对象,代码如下:

MyThread 类继承了 Thread 对象,并重写(Override)了 run 方法,实现线程里面的逻辑。main 函数是使用 for 语句,循环创建了 10 个线程,调用 start 方法启动线程,最后打印当前线程对象的 ID。

run 方法和 start 方法的区别是什么呢?

run 方法就是跑的意思,线程启动后,会调用 run 方法。
start 方法就是启动的意思,就是启动新线程实例。启动线程后,才会调线程的 run 方法。

执行 main 方法后,控制台打印如下:

可见,线程的 ID 是线程唯一标识符,每个线程 ID 都是不一样的。

start 方法和 run 方法的关系如图所示:

同理,实现 Runnable 接口类创建线程对象也很简单,只是不同的形式。新建 MyThreadBrother 代码如下:

2.1 线程的运行

在运行上面两个小 demo 后,JVM 执行了 main 函数线程,然后在主线程中执行创建了新的线程。正常情况下,所有线程执行到运行结束为止。除非某个线程中调用了 System.exit(1) 则被终止。

在实际开发中,一个请求到响应式是一个线程。但在这个线程中可以使用线程池创建新的线程,去执行任务。

3、线程的状态

新建 MyThreadInfo 类,打印线程对象属性,代码如下:

执行代码打印如下:

线程是一个对象,它有唯一标识符 ID、名称、状态、优先级等属性。线程只能修改其优先级和名称等属性,无法修改 ID、状态。ID 是 JVM 分配的,名字默认也为 Thread-XX,XX 是一组数字。线程初始状态为 NEW。

线程的状态实现通过 Thread.State 常量类实现,有 6 种线程状态:new(新建)、runnnable(可运行)、blocked(阻塞)、waiting(等待)、time waiting(定时等待)和 terminated(终止)。状态转换图如下:

线程状态流程大致如下:

各种状态一目了然,线程状态流程大致如下:

  • 线程创建后,进入 new 状态
  • 调用 start 或者 run 方法,进入 runnable 状态
  • JVM 按照线程优先级及时间分片等执行 runnable 状态的线程。开始执行时,进入 running 状态
  • 如果线程执行 sleep、wait、join,或者进入 IO 阻塞等。进入 wait 或者 blocked 状态
  • 线程执行完毕后,线程被线程队列移除。最后为 terminated 状态。

4、小结

本文介绍了线程与多线程的基础篇,包括了线程启动及线程状态等。如果有神呢么问题,欢迎一起交流~

免费获取更多安卓开发架构的资料(包括 Fultter、高级 UI、性能优化、架构师课程、NDK、Kotlin、混合式开发(ReactNative+Weex)和一线互联网公司关于 android 面试的题目汇总可以加入【腾讯 @安卓中高级进阶】
退出移动版