进程和线程
进程和线程
对于操作系统来说,一个任务就是一个进程。比如打开一个浏览器就是启动了一个浏览器进程。打开了一个记事本就是启动了一个记事本进程。
某些进程还不止同时干一件事情,比如word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部需要同时做多件事,因此就需要同时运行多个“子任务”。我们把进程内部的这些“子任务”称作线程。
由于每个进程至少要干一件事,所以一个进程至少要有一个线程。一些复杂的程序进程下会有N个线程,多个线程可以同时执行。与多进程类似,多线程的执行方式也是由操作系统在多个线程之间快速切换,每个线程交替短暂执行,看起来就像同时执行一样。但是真正的执行多线程需要多核CPU才可能实现。
进程是代码在数据集合上的一次运行活动,进程是系统进行资源分配和调度的基本单位。
线程是进程中的一个实体,线程本身是不会独立存在的。线程是进程的一个执行路径,多个线程共享进程的资源。但是线程是CPU分配的基本单位,因为真正要占用CPU运行的是线程。
在java中,当我们启动main函数时,其实就是启动了一个jvm进程,在main函数所在的线程就是这个进程中的一个线程,也叫主线程。
JVM中一个进程中的多个线程共享进程的堆和方法区资源,每个线程有自己的程序计数器和栈区域。
每个线程都拥有一个程序计数器的原因 在上面也提到了,因为线程是CPU分配的节本单位,而CPU一般是使用时间片轮转方式让线程轮询占用的,所以当前线程CPU时间片用完以后需要让出CPU。等下次轮到自己的时候再执行。而程序计数器就是为了记录在让出CPU时,在本线程内CPU的执行地址。以方便再次分配到时间片时候,线程就可以从上次挂起的地址再次执行。
由于在进程中,每个子任务都是一个线程,所以每个线程都拥有一个栈资源用于存放该线程的局部变量,这些局部变量是私有的,其他线程是访问不了的。除此以外栈还用来存放线程的调用栈帧。

并行和并发
并行(parallel):指在同一时刻,有多条指令在多个处理器上同时执行
并发(concurrency):指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上(同一时间段内)具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个进程快速交替的执行。
为什么需要多编程
多线程的产生是为了提高对cpu的利用率,但由于多线程的出现,也带来了3个问题
分别是可见性问题、原子性问题以及有序性问题
可见性:CPU、缓存、内存之间的速度差异导致了可见性问题;
原子性:CPU的分时复用导致线程会被切换,导致原子性问题
有序性:JVM对代码的执行顺序的优化导致了有序性问题
线程状态
线程中的状态共分为六种(更具体的说是7个,因为运行态包括就绪和运行中,但建议将两者合为一体看待,因为都进入了就绪队列):
初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
运行(RUNNABLE):Java线程中将
就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。阻塞(BLOCKED):表示线程阻塞于锁。
等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
终止(TERMINATED):表示该线程已经执行完毕。
阻塞态和等待态的不同之处:阻塞态:被动阻塞,一个线程试图获取锁时,而该锁被其他线程持有,则该线程进入阻塞状态。
等待态:线程抢到了锁进入了同步代码块,但因为某些原因(Object.wait())导致线程进入了waiting态,Waiting线程被其他线程调用Object.notify()唤醒之后,重新获取对象上的锁的时候也会进入Blocked状态

线程的各个方法
调用 Thread.sleep() 方法使线程进入限期等待状态时,常常用“使一个线程睡眠”进行描述。
调用 Object.wait() 方法使线程进入限期等待或者无限期等待时,常常用“挂起一个线程”进行描述。
睡眠和挂起是用来描述行为,而阻塞和等待用来描述状态。
阻塞和等待的区别在于,阻塞是被动的,它是在等待获取一个排它锁。而等待是主动的,通过调用 Thread.sleep() 和 Object.wait() 等方法进入。
| 进入方法 | 退出方法 |
|---|---|
| Thread.sleep() 方法 | 时间结束 |
| 设置了 Timeout 参数的 Object.wait() 方法 | 时间结束 / Object.notify() / Object.notifyAll() |
| 设置了 Timeout 参数的 Thread.join() 方法 | 时间结束 / 被调用的线程执行完毕 |
著作权归https://www.pdai.tech所有。 链接:https://www.pdai.tech/md/java/thread/java-thread-x-thread-basic.html
yield()
对静态方法 Thread.yield() 的调用声明了当前线程已经完成了生命周期中最重要的部分,可以切换给其它线程来执行。该方法只是对线程调度器的一个建议,而且也只是建议具有相同优先级的其它线程可以运行。

浙公网安备 33010602011771号