一、引言
学习并发编程之前,我们先了解几个概念:
什么是进程,什么是线程?
- 进程是一个 “执行中的程序”,是系统进行资源分配和调度的一个独立单位。
- 线程是进程的一个实体,一个进程中拥有多个线程,线程之间共享地址空间和其它资源(所以通信和同步等操作线程比进程更加容易)。
- 线程上下文的切换比进程上下文切换要快很多。
- (1)进程切换时,涉及到当前进程的 CPU 环境的保存和新被调度运行进程的 CPU 环境的设置。
- (2)线程切换仅需要保存和设置少量的寄存器内容,不涉及存储管理方面的操作。
什么是单线程,什么是多线程?
- 单线程:在单核 CPU 中,将 CPU 分为很小的时间片,在每一时刻只能有一个线程在执行,是一种微观上轮流占用 CPU 的机制。
- 多线程:存在线程上下文切换,会导致程序执行速度变慢,即采用一个拥有两个线程的进程执行所需要的时间比一个线程的进程执行两次所需要的时间要多一些。
结论:采用多线程不会提高程序的执行速度,反而会降低程序的执行速度,但是对于用户来说,可以减少用户的响应时间。
什么是同步,什么是异步?
同步方法调用:方法调用一旦开始,调用者必须等到方法返回后,才能继续后续的行为。
异步方法调用:异步方法更像是一个消息传递,一旦开始,方法调用就会立即返回,调用者就可以继续后续的操作。
多线程有什么优势?
- 资源利用率更好
- 程序设计在某些情况下更简单
- 程序响应更快
PS:多线程不一定快。数据量小的时候,涉及到线程的创建和上下文切换,此时反而比单线程慢。
二、线程的状态
线程一共有六种状态,并且某个时刻 Java 线程只能处于其中的一个状态。
新建(NEW)
表示新创建了一个线程对象,而此时线程并没有开始执行。
可运行(RUNNABLE)
线程对象创建后,其它线程(比如 main 线程)调用了该对象的 start() 方法,才表示线程开始执行。当线程执行时,处于 RUNNBALE 状态,表示线程所需的一切资源都已经准备好了。该状态的线程位于可运行线程池中,等待被线程调度选中,获取 cpu 的使用权。
阻塞(BLOCKED)
如果线程在执行过程终遇到了 synchronized 同步块,就会进入 BLOCKED 阻塞状态,这时线程就会暂停执行,直到获得请求的锁。
等待(WAITING)
当线程等待另一个线程通知调度器时,它自己进入等待状态。在调用Object.wait方法或Thread.join方法,或者是等待java.util.concurrent库中的Lock或Condition时,就会出现这种情况。
计时等待(TIMED_WAITING)
Object.wait、Thread.join、Lock.tryLock和Condition.await 等方法有超时参数,还有 Thread.sleep 方法、LockSupport.parkNanos 方法和 LockSupport.parkUntil 方法,这些方法会导致线程进入计时等待状态,如果超时或者出现通知,都会切换会可运行状态。
终止(TERMINATED)
当线程执行完毕,则进入该状态,表示结束。
PS:从 NEW 状态出发后,线程不能再回到 NEW 状态,同理,处于 TERMINATED 状态的线程也不能再回到 RUNNABLE 状态。