程序:是为了完成特定任务,用某种语言编写的一组指令组合。一段静态代码。
进程:是程序的一次执行过程,或是正在运行的一个程序,是一个动态的过程,有它自身的产生、存在和消亡的过程—生命周期
-
如:运行的qq
-
程序是静态的,进程是动态的
-
进程作为资源分配的单位,系统在运行时为每一个进程分配不同的内存区域
程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程
为什么引入进程的概念?
在很久之前,计算机是用户敲一个命令在运行的,如果用户不敲命令,那么计算机就会等待,这样显的很呆。所以有人想出了批处理系统,把写好的程序写在磁带上,让cpu批处理。但是这会导致一个问题就是,任务A在请求IO的时候,cpu要等任务A请求IO完之后才能运行任务A,在等待的过程中,cpu是空闲的,所以导致效率不高。
这时候又出现了几个问题,内存中始终都只有一个程序在运行,如果想要解决上面的问题,就必然要在内存中装入多个程序,那么计算机是如何辨别不同程序的标记呢?程序所需要的资源又是如何辨别的呢?暂停之后又如何恢复到之前的程序呢?
**所以进程就出现了,**用进程来对应程序,每个进程来对应一定的内存地址空间,并且每个进程只能使用自己的内存空间,各个进程互不干扰,进程里面包含PCB(进程管理块),它里面包含进程的各种信息。
线程:进程可以进一步细化为线程,是一个程序内部的一条执行路径
- 若一个进程同一时间并行执行多个线程,就是支持多线程的
- 线程作为调度和执行的单位,每个线程都拥有独立的运行栈和程序计数器,线程的切换开销小。
- 一个进程中的多个线程共享相同的内存单元/内存地址空间->它们从同一堆中分配对象,可以访问相同的变量和对象(方法区,堆),这就会导致线程间的通信便捷,但多个线程操作共享的资源可能会导致安全的隐患,例如死锁。
为什么有了进程还要出现线程这个概念?
人们对实时性有了要求,因为一个进程在一个时段内只能做一个事情,如果一个进程有多个子任务的时候,只能逐个执行,很影响效率。所以人们在想能不能在同一时间内进程的里面任务分多个路径去执行。让一个线程去执行一个子任务,一个进程包含一个以上的线程,让用户感觉系统在同时做很多事,满足用户的实时性。例如360软件,一边杀毒,一边清理垃圾,就是多线程。
线程和进程的区别?
一个进程是一个独立的运行环境,它可以被看作一个程序,或者一个应用,而线程是进程中执行的一个子任务。
从内存:进程单独占用内存地址空间,而线程是共享进程的内存地址空间。
从调度:进程是资源分配的最小单位,线程是cpu调度的最小单位。
从 资源开销 :程序之间切换会有较大的开销,每个线程都有自己的独立的运行栈和PC,线程之间切换的开销小
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kTnuLcus-1621394040110)(每天一积累.assets/1621335560188.png)]
线程的生命周期
线程同步方式
方式一同步代码块
synchronized(同步监视器){
//同步的代码
}
说明:
- 操作共享数据的代码,即为需要被同步的代码
- 共享数据,多个线程共同操作的变量,例如:ticket就是共享数据,使用implements Runable的方式创建线程,子类只创建一次,那么子类里面的成员变量ticket就只存在一份,又因为多个线程的构造器传入了这个子类的对象,所以实现了共享数据
- 同步监视器,俗称:锁。任何一个类的对象,都可以充当锁。要求:多个线程必须要共用同一把锁
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YuC7esZP-1621394040113)(每天一积累.assets/1621389265153.png)]
同步的方式,解决了线程的安全问题。
但是操作同步代码时,只能有一个线程参与,其他线程等待,相当于一个单线程的过程,效率低。
关于同步方法的总结:
-
同步方法仍然涉及到同步监视器,只是不需要我们显示的声明。
-
非静态的同步方法,同步监视器是:this
静态的同步方法,同步监视器是:当前类的本身
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mwVMG5IG-1621394040114)(每天一积累.assets/1621348394582.png)]
lock的方式
实现2个线程交叉买票
package com.example.demo;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class test_thread4 implements Runnable{
private int ticket = 100;
Lock lock = new ReentrantLock();//获取lock的实现类
@Override
public void run() {
while(true) {
if (ticket > 0) {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + "线程" + ticket + "票");
ticket--;
} finally {
lock.unlock();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
test_thread4 t4 = new test_thread4();
Thread thread = new Thread(t4);
Thread thread1 = new Thread(t4);
thread.start();
thread1.start();
}
}
参考:https://blog.csdn.net/whl_program/article/details/70217354