目录
一、进程
进程是操作系统中一种非常重要的软件资源,当我们把一个可执行程序exe运行起来的时候,系统就会随之创建一个进程,如果这个程序结束系统会随之销毁对应的进程。
当运行exe文件时,exe文件中的很多内容都加载到内存中,通过分配资源来执行这个程序包含的指令的过程叫做进程。
进程的管理是通过先描述在组织的方法:
在Linux中每创建一个进程就会创建一个PCB这样的类的实例
创建一个进程,本质上就是在内核中先创建一个PCB对象,然后将这个对象加入到链表中。
结束一个进程的时候,本质上就是在内核中找到这个PCB对象,将他从链表中删除,并且释放该对象。
我们通过任务管理器中看到的所以的进程信息就是在内核中遍历该链表,依次读取PCB中的信息。
PCB中包含的信息:
1、进程id----进程的身份标识。
2、一组内存指针----指向该进程持有的一些重要数据在内存中的位置。
以及状态、优先级、进程的记账信息、上下文,这些模块交做调度器来实现进程模块的调度,
为了让这么多进程可以在有限的CPU上并发执行。
状态:判断是在运行还是在休眠等······
优先级:判断这个进程是优先在CPU上执行还是放到后面······
进程的记账信息:记录进程在CPU上执行的时间,通过时间来限制一段进程的执行······
上下文:保存进程在CPU上执行的进度,方便下次继续执行······
二、线程
所谓的线程其实是一种轻量级的进程
1、一个进程中包含多个线程
2、相比于进程成本更低,大部分资源是和原来的线程共享的,主要共享内存资源和打开的文件,上下文等是不能共享的。
3、每个线程都有一段自己的执行逻辑,每个线程都是一个独立的执行流。
注意:当创建出一个进程时,会随之创建一个主线程。
线程中的管理模式和进程中的一样都是先描述在组织。
一个线程和一个PCB对应,一个进程可能和多个PCB对应,在PCB中会有线程组id来对应一组线程。
进程中最多可以有多少个线程取决于:
1、CPU的个数。
2、和线程执行的任务类型也相关(CPU密集性和IO密集性)。
三、进程和线程的区别
根本区别:进程是操作系统分配资源的最小单位,线程是任务调动和执行的最小单位。
在开销方面:每个进程都有独立的代码和数据空间,程序切换会有较大的开销。线程之间共享代码和数据,每个线程都有自己独立的栈和调度器,线程之间的切换的开销较小。
所处环境:一个操作系统中可以运行多个进程,一个进程中有多个线程同时执行。
内存分配方面:系统在运行时会为每个进程分配内存,系统不会单独为每个线程分配内存。
包含关系:创建进程时系统会自动创建一个主线程由主线程完成,进程中有多线程时,由多线程共同执行完成。
四、多线程的创建和常见方法
1、多线程的创建
1、通过创建类继承Thread来调用
//1、通过类直接创建
static class MyThread extends Thread{
@Override
public void run() {
System.out.println("qewrwerwerw");
}
}
public static void main(String[] args) {
Thread t=new MyThread();
t.start();
}
2、通过Thread匿名内部类进行调用
public static void main(String[] args) {
Thread t=new Thread(){
@Override
public void run() {
System.out.println("wefwefwef");
}
};
t.start();
}
3、通过创建类实现Runnable接口实现
static class MyThread implements Runnable{
@Override
public void run() {
System.out.println("awetqeragearga");
}
}
public static void main(String[] args) {
Thread t=new Thread(new MyThread());
t.start();
}
4、通过Runnable实现匿名内部类调用实现
public static void main(String[] args) {
Runnable runnable=new Runnable() {
@Override
public void run() {
System.out.println("w3rqetqwetqw");
}
};
Thread r=new Thread(runnable);
r.start();
}
5、通过lambad表达式调用
public static void main(String[] args) {
Thread t=new Thread(()->System.out.println("asdasfasfasfas"));
t.start();
}
2、多线程的常用方法
2.1、多线程的构造方法
方法 | 解释 |
Thread() | 创建线程对象 |
Thread(Runnable target) | 使用Runnable类型创建对象 |
Thread(String name) | 创建线程对象并命名 |
Thread(Runnable target,String name) | 使用Runnable类型创建对象并命名 |
例:
public static void main(String[] args) {
Thread t=new Thread("我是你爸爸"){
@Override
public void run() {
System.out.println("你好");
while (true){
}
}
};
t.start();
while(true){
}
}
2.2、线程的常见属性
属性 | 获取方法 |
ID | getId() |
名称 | getName() |
状态 | getState() |
优先级 | getPriority() |
是否后台线程 | isDaemon() |
是否存活 | isAlive() |
是否被中断 | isInterrupted() |
2.3、中断程序
1)让线程run执行(比较温和)
private static boolean cread=false;
public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(){
@Override
public void run() {
while(!cread){
System.out.println("转账中");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
Thread.sleep(2000);
System.out.println("有内鬼终止交易");
cread=true;
}
2)调用线程的interrupt方法来(比较激烈)
public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(){
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()){
System.out.println("转账中");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
//break;
}
}
System.out.println("转账被终止");
}
};
t.start();
Thread.sleep(2000);
System.out.println("有内鬼终止交易");
t.interrupt();
}
Thread.interrupted()判断当前线程中断标志被设置--清除中断
Thread.currentThread().isInterrupted()判断指定线程的中断标志--不清除中断标志
2.4、线程的等待和休眠
线程之间是并发执行的
线程的等待:
我们可以通过join方法来阻塞线程,join为了控制线程结束的先后顺序。
public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(){
@Override
public void run() {
for(int i=0;i<3;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我在执行t1");
}
}
};
Thread t2=new Thread(){
@Override
public void run() {
for(int i=0;i<3;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我在执行t2");
}
}
};
t2.start();
t1.start();
t2.join();
t1.join();
}
当两个线程执行完成之后,主线程才会继续向下执行,我们可以通过这种方法来获取时间。
线程的休眠 :