线程与进程
进程:是指⼀个内存中运⾏的应⽤程序,每个进程都有⼀个独⽴的内存空间,⼀个应⽤程序可以同时运⾏多个进程;进程也是程序的⼀次执⾏过程,是系统运⾏程序的基本单位;系统运⾏⼀个程序即是 ⼀个进程从创建、运⾏到消亡的过程。
线程:线程是进程中的⼀个执⾏单元,负责当前进程中程序的执⾏,⼀个进程中⾄少有⼀个线程。⼀个进程中是可以有多个线程的,这个应⽤程序也可以称之为多线程程序。
简⽽⾔之:⼀个程序运⾏后⾄少有⼀个进程,⼀个进程中可以包含多个线程
并发与并⾏
并发:指两个或多个事件在同⼀个时间段内发⽣。
并⾏:指两个或多个事件在同⼀时刻发⽣(同时发⽣)。
线程调度:
-
分时调度
所有线程轮流使⽤ CPU 的使⽤权,平均分配每个线程占⽤ CPU 的时间。
-
抢占式调度
优先让优先级⾼的线程使⽤ CPU,如果线程的优先级相同,那么会随机选择⼀个(线程随机性), Java使⽤的为抢占式调度。
设置线程的优先级
抢占式调度详解
⼤部分操作系统都⽀持多进程并发运⾏,现在的操作系统⼏乎都⽀持同时运⾏多个程序。⽐如: 现在我们上课⼀边使⽤编辑器,⼀边使⽤录屏软件,同时还开着画图板, dos 窗⼝等软件。此时,这些程序是在同时运⾏, “ 感觉这些软件好像在同⼀时刻运⾏着 ” 。
实际上,CPU (中央处理器)使⽤抢占式调度模式在多个线程间进⾏着⾼速的切换。对于 CPU 的 ⼀个核⽽⾔,某个时刻,只能执⾏⼀个线程,⽽ CPU 的在多个线程间切换速度相对我们的感觉 要快,看上去就是在同⼀时刻运⾏。
其实,多线程程序并不能提⾼程序的运⾏速度,但能够提⾼程序运⾏效率,让 CPU 的使⽤率更⾼。
创建线程,是希望线程成为一个独立的执行流(执行一段代码)
使用Thread类,不需要import别的包
如果只是 直接打印hello world,你的java进程调用main方法的线程——主线程
通过t.start(),主线程调用t.start(),创建出一个新线程,新线程调用t.run()
run方法执行完毕,新线程自然销毁
面试问题:
☆start和run之间的区别
1.start方法用于启动线程,run方法只是Thread子类的一个普通方法
2.当使用start方法启动线程后,线程会运行类中的run方法
start是真正创建了一个线程(从系统这里创建的),线程是独立的执行流
run只是描述了线程要干的活是啥,如果直接在main中调用run,此时没有创建新线程,全是main线程一个人干活
PCB(进程控制块)对应的是 线程
一个线程对应一个PCB
一个进程对应多个PCB
如果一个进程只有一个线程的情况,就是一个进程对应一个PCB了
同一个进程里的若干PCB的pid相同,不同进程的pid是不同的
public class ThreadDemo1 {
public static void main(String[] args) {
Thread t = new MyThread();//new对象操作不创建线程
//t.run();//虽然t是父类引用,但此处调用的是重写的子类run方法(t本质上还是指向子类的对象)
t.start();//线程中的特殊方法——启动一个线程
}
注意:start里面没有调用run!!!
start是创建了一个线程,由新的线程来执行t.run()方法
就是调用操作系统的API,通过操作系统内核创建新线程的PCB,并且把要执行的指令交给这个PCB
当PCB被调度到CPU上执行时,也就执行到了线程run方法中的代码了
抢占式执行,随机调度
问:main每次都是比thread先出现吗?
答:不一定谁先谁后。操作系统调度线程是“抢占式执行”,具体哪个线程先,不确定,取决于操作系统调度器具体实现策略
虽然有优先级,但是在应用程序层面上无法修改
扩展:为什么会有线程安全问题?罪魁祸首就是抢占式执行,随机调度