热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入解析Java中的进程与线程机制

在Java中,进程与线程是程序执行的基本单元。进程代表了程序的运行实例,包含了独立的内存空间和系统资源,如CPU时间、内存、文件和I/O接口。操作系统通过进程来管理和分配这些资源,确保每个程序能够高效、安全地运行。线程则是进程内的基本调度单位,多个线程可以共享进程的资源,从而实现高效的并发处理。本文将深入探讨Java中的进程与线程机制,分析其工作原理和应用场景。

进程与线程


前言

进程可以看作是程序的执行过程。一个程序的运行需要CPU时间、内存空间、文件以及I/O等资源。操作系统就是以进程为单位来分配这些资源的,所以说进程是分配资源的基本单位。


进程是动态的,程序是静态的

程序是静态的,它本身作为一种软件资源可以长期保存在磁盘(常说的硬盘)中。比如QQ,QQ作为一个程序,其本身保存在计算机的磁盘上。此时,它并没有得到CPU、内存、I/O等资源。因此当前的QQ程序只是一个静态的程序并不能给我们实现视频、语音等功能。

但当QQ程序开始执行时,操作系统就会将QQ程序从磁盘中装入内存,同时也会在操作系统中创建属于QQ的进程,这些新创建的QQ进程会得到操作系统分配的CPU、内存、I/O等资源,得到这些资源后,创建出来的QQ进程就可以实现视频和语音的功能。而当我们点击退出QQ后,这些进程就会立刻消亡,分配得到的资源也会被释放。

由此可以看出,QQ进程是QQ程序的执行过程,它是动态的,有一定的生命周期,会动态的产生和消亡。进程是资源分配的单位。


程序与进程并不是一 一对应的关系虽然进程可以看作是程序的执行过程,但并非一个程序对应一个进程,即二者并不是一 一对应的关系。程序与进程的关系可能有以下几种:

一个程序产生一个进程

比如Win10的记事本程序(notepad.exe),每打开一个txt文本文件,就只会启动一个记事本进程。

一个程序产生多个进程

比如浏览器启动时,一般都会产生多个进程,这些进程相互配合,互相影响,共同实现浏览器的功能。

一个程序可以被多个进程共用

比如一个记事本程序在执行时,就只会产生一个进程。但当我们再用记事本程序打开一个文件时,此时就会再次在操作系统中创建一个新的进程,这个新的进程同样也会调用记事本程序。即在此刻,计算机磁盘中只有一个记事本程序,但是操作系统中却有两个记事本进程在共用这个程序,且这两个进程互不影响。

一个进程又可能要用到多个程序

比如,用C语言写了一个helloword.c的程序。此时,输入命令gcc helloword.c。那么操作系统会创建一个进程,它调用c编译程序,对helloword.c文件进行编译。这个进程在执行编译的过程中,除了调用c编译程序和我们编写的helloword程序外,还会用到c预处理程序、连接程序、结果输出程序等。

而线程从属于进程,只能在进程的内部活动,多个线程共享进程所拥有的的资源。如果把进程看作是完成许多功能的任务的集合,那么线程就是集合中的一个任务元素,负责具体的功能。虽然CPU、内存、I/O等资源分配给了进程,但实际上真正利用这些资源并在CPU上执行的却是线程,即真正完成程序功能的是线程。

因为进程作为这些资源的拥有者,它的负载很重,在进程的创建、切换、删除过程中的时间和空间开销都很大。所以目前主流的操作系统都只将进程作为资源的拥有者,而把CPU调度和运行的属性赋予了线程。

比如打开浏览器程序,会产生相应的进程,浏览器进程中包含有许多线程,如HTTP请求线程,I/O线程,渲染线程,事件响应线程等。浏览器进程拥有着内存和I/O资源等,但当我们在浏览器中输入文字时,真正使用I/O资源接收我们输入的文字,并在CPU处理文字的却是浏览器进程中的I/O线程。即真正完成浏览器文字输入功能的是线程。


 线程与进程的关系

①一个进程可以有多个线程,但至少要有一个线程,并且一个线程只能在一个进程的地址空间内活动。
②资源分配给进程,而一个进程内的所有线程共享该进程的所有资源。
③CPU分配给的是线程,即真正在CPU上运行的是线程。
④进程间通信较为复杂,同一台计算机的进程通信称为 IPC(Inter-process communication)。
而不同计算机之间的进程通信,则需要通过网络,并遵守共同的协议,例如 HTTP等。
⑤线程通信相对简单,因为它们共享进程内的内存,一个例子是多个线程可以访问同一个共享变量。
⑥线程更轻量,线程上下文切换成本一般上要比进程上下文切换低。

package Data20221010.test1.t1;public class Wait {public static void bySec(long s){int i;for ( i=1;i<=s;i++){
// System.out.println(i+"秒");try{Thread.sleep(1000);// 时间}catch (InterruptedException e){e.printStackTrace();}}System.out.println(i-1+"秒");}
}

package Data20221010.test1.t1;public class test {public static void main(String[] args) {String thread = Thread.currentThread().getName();System.out.println(thread+"线程开始运行");Wait.bySec(10);}
}

抢票示例:

package Data20221011.dom1;
/*** 线程不安全的网络抢票**/
public class Site implements Runnable{private int count=10; //记录剩余票数 private int num = 0; //记录买到第几张票public void run(){while(true){//没有余票时,跳出循环if(count<=0){break;}//第一步:修改数据num++;count--;try {Thread.sleep(500); //模拟网络延时} catch (InterruptedException e) { e.printStackTrace();} //第二步:显示信息System.out.println(Thread.currentThread().getName()+"抢到第"+num+"张票,剩余"+count+"张票!"); }}
}

package Data20221011.dom1;public class Test {public static void main(String[] args) {Site site = new Site();Thread person1= new Thread(site,"桃跑跑");Thread person2= new Thread(site,"抢票代理");Thread person3= new Thread(site,"黄牛党");System.out.println("********开始抢票********");person1.start();person2.start();person3.start();}
}
// 多线程操作共享数据,容易引发数据不安全的问题


推荐阅读
author-avatar
传导网络
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有