进程和线程都是操作系统中用于管理程序执行的概念。
进程是操作系统中的一个独立的执行单元,它包含了程序代码、数据、打开的文件、系统资源等信息。每个进程都有自己的内存空间和系统资源,不同的进程之间是相互独立的,它们不能直接访问彼此的内存空间和系统资源。进程的创建、销毁和切换都需要操作系统的支持,因此进程的开销比较大。
线程是进程中的一个执行单元,它是进程中的一个轻量级的执行流。每个线程都共享进程的内存空间和系统资源,不同的线程之间可以直接访问共享的内存空间和系统资源。线程的创建、销毁和切换比进程要快,因为它们不需要操作系统的支持,只需要使用线程库中的函数即可。
总之,进程和线程都是用于管理程序执行的概念,进程是操作系统中的一个独立的执行单元,线程是进程中的一个轻量级的执行流。进程和线程之间的区别在于内存空间和系统资源的共享方式,以及创建、销毁和切换的开销。
进程状态的转换
·就绪态→运行态:处于就绪态的进程被调度后,获得处理机资源(分派处理机时间片),于是进程由就绪态转换为运行态。
。运行态→就绪态:处于运行态的进程在时间片用完后,不得不让出处理机,从而进程由运行态转换为就绪态。此外,在可剥夺的操作系统中,当有更高优先级的进程就绪时,调度程序将正在执行的进程转换为就绪态,让更高优先级的进程执行。
·运行态一阻塞态:进程请求某一资源(如外设〉的使用和分配或等待某一事件的发生(如I/O操作的完成)时,它就从运行态转换为阻塞态。进程以系统调用的形式请求操作系统提供服务,这是一种特殊的、由运行用户态程序调用操作系统内核过程的形式。
阻塞态→就绪态:进程等待的事件到来时,如IO操作结束或中断结束时,中断处理程序必须把相应进程的状态由阻塞态转换为就绪态。
(1)线程中等待唤醒机制:
线程中等待唤醒机制是指线程在某些条件下被挂起,等待某些条件满足后被唤醒继续执行的机制。在Java中,线程的等待唤醒机制主要是通过wait()、notify()和notifyAll()方法来实现的。
当一个线程执行wait()方法时,它会释放持有的锁并进入等待状态,直到其他线程调用notify()或notifyAll()方法来唤醒它。notify()方法会随机唤醒一个正在等待的线程,而notifyAll()方法会唤醒所有正在等待的线程。被唤醒的线程会重新尝试获取锁并继续执行。
等待唤醒机制通常用于线程间的协作,例如生产者-消费者模型中,当队列为空时消费者线程会等待生产者线程生产数据并唤醒它,当队列满时生产者线程会等待消费者线程消费数据并唤醒它。通过等待唤醒机制,可以避免线程不必要的轮询和浪费CPU资源,提高程序的效率。
(2)经典的消费者问题:
顾客卖包子,店铺生产包子。
包子类(为简单演示,不再写入构造方法以及set和get方法)
public class Baozi {
String pi;
String xian;
Boolean flag=false;
}
用包子店铺模拟线程一
//包子铺生产包子
public class BaoZiPu extends Thread {
private Baozi baozi;
public BaoZiPu(String name, Baozi baozi) {
super(name);
this.baozi = baozi;
}
int x=100;//假设包子铺一天生产100个包子
@Override
public void run() {
int m=0;
while (x>0) {
synchronized (baozi) {
if (baozi.flag==true){
try { baozi.wait(); }catch (InterruptedException e){e.printStackTrace();}
}
System.out.println("包子铺生产包子");
try {
Thread.sleep(180);//模拟做包子的过程耗费的时间
} catch (InterruptedException e) {
e.printStackTrace();
}
if (m%2==0){
baozi.pi="玉米面作皮";
baozi.xian="香菇肉丁做馅";
}else {
baozi.pi="白面作皮";
baozi.xian="雪菜做馅";
}
m++;x--;
System.out.println(baozi.pi+","+baozi.xian+"的包子一个"+",做的第"+(100-x)+"包子\n");
baozi.flag=true;
//唤醒
baozi.notify();
}
}
}
}
用顾客来模拟线程二
public class Guke extends Thread {
private Baozi baozi;
public Guke(String name, Baozi baozi) {
super(name);
this.baozi = baozi;
}
@Override
public void run() {
while (true) {
synchronized (baozi) {
if (baozi.flag == false) {
try {
baozi.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("顾客吃包子。。。。");
System.out.println("顾客吃" + baozi.pi + "," + baozi.xian + "的包子");
try {
Thread.sleep(40);//模拟顾客吃包子的过程所耗费的时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("包子吃完了");
baozi.flag = false;
baozi.notify();
}
}
}
}
定义测试类,来模拟该过程
public class Test {
public static void main(String[] args) {
Baozi baozi=new Baozi();//以包子作为共同的资源
//线程一顾客
Guke guke=new Guke("顾客",baozi);
//线程二包子铺
BaoZiPu baoZiPu=new BaoZiPu("包子铺",baozi);
guke.start();
baoZiPu.start();
}
}
运行实例如下:(为方便演示,只显示前5个包子生产与消耗的模拟)
包子铺生产包子
玉米面作皮,香菇肉丁做馅的包子一个,做的第1包子
顾客吃包子。。。。
顾客吃玉米面作皮,香菇肉丁做馅的包子
包子吃完了
包子铺生产包子
白面作皮,雪菜做馅的包子一个,做的第2包子
顾客吃包子。。。。
顾客吃白面作皮,雪菜做馅的包子
包子吃完了
包子铺生产包子
玉米面作皮,香菇肉丁做馅的包子一个,做的第3包子
顾客吃包子。。。。
顾客吃玉米面作皮,香菇肉丁做馅的包子
包子吃完了
包子铺生产包子
白面作皮,雪菜做馅的包子一个,做的第4包子
顾客吃包子。。。。
顾客吃白面作皮,雪菜做馅的包子
包子吃完了
包子铺生产包子
玉米面作皮,香菇肉丁做馅的包子一个,做的第5包子
顾客吃包子。。。。
顾客吃玉米面作皮,香菇肉丁做馅的包子
包子吃完了
实机截图