热门标签 | 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();}
}
// 多线程操作共享数据,容易引发数据不安全的问题


推荐阅读
  • 程序连接MySQL数据库的多种方法详解 ... [详细]
  • 微软发布紧急安全更新,所有Windows 10版本均面临影响!
    微软于周五紧急发布了两项安全更新,旨在解决Windows 10所有版本中Windows Codecs库和Visual Studio Code应用存在的安全隐患。此次更新是继本周初发布的月度例行安全补丁之外的额外措施,凸显了这些问题的紧迫性和重要性。这些漏洞可能被攻击者利用,导致系统权限提升或远程代码执行等严重后果。建议用户尽快安装更新,以确保系统的安全性。 ... [详细]
  • 本文通过复旦大学自然语言处理课程中的一个具体案例,详细解析了中文词汇分割技术的实现方法。该案例利用Java编程语言,结合词典和算法模型,展示了如何高效地进行中文文本的词汇分割,为相关研究和应用提供了宝贵的参考。 ... [详细]
  • Java包功能详解:初学者指南(附带教学视频解析)
    本文详细解析了Java包的功能及其对初学者的重要性,并通过教学视频进行辅助讲解。文章首先介绍了包的主要作用,包括避免类和方法的命名冲突以及便于管理和组织大量的Java类。随后,逐步引导读者了解工具包中的各个工具类,如StringUtil等,并详细说明了如何配置CLASSPATH环境变量,确保项目中能够正确引用这些类。 ... [详细]
  • Oracle培训(三十七)——深入解析Hibernate第三章:实体关联关系映射详解
    在本节Oracle培训中,我们将深入探讨Hibernate第三章的内容,重点讲解实体关联关系映射的详细知识点。首先,回顾了Hibernate的基本概念和映射基础,随后详细分析了不同类型的实体关联关系,包括一对一、一对多和多对多关系的映射方法及其应用场景。通过具体的示例和代码片段,帮助读者更好地理解和掌握这些复杂的映射技术。此外,还讨论了如何优化关联关系的性能,以及常见的问题和解决方案。 ... [详细]
  • 深入解析JDK中的四种随机数生成器
    我们从jdk8说起。主要是四个随机数生成器。神马?有四个? 接下来我们简单说下这几个类的使用场景,来了解其中的细微差别,和a ... [详细]
  • `ArrayDeque` 类中的 `removeLast()` 方法用于移除并返回双端队列中的最后一个元素。该方法在处理数据结构时非常有用,特别是在需要高效地从队列末尾移除元素的场景中。本文将详细介绍 `removeLast()` 方法的工作原理,并通过具体的应用实例展示其使用方法和优势。 ... [详细]
  • 本文探讨了Huffman树在数据结构中的应用及其原理。Huffman树,即哈夫曼树,是一种高效的数据压缩技术,通过构建最优二叉树实现编码,广泛应用于文件压缩和网络传输中,有效减少数据存储和传输的空间需求。 ... [详细]
  • 下面的代码旨在输出其类文件的完整名称。对于不熟悉类字面量的读者,`Me.class.getName()` 方法会返回类的全称,例如 “com.javapuzzlers.Me”。通过这一机制,可以深入了解 Java 类加载和反射机制的内部工作原理。 ... [详细]
  • Java进阶之旅:第六阶段深度解析与实践
    在之前的Java进阶之旅中,我们已经深入探讨了Java语言的核心特性,包括继承、封装和多态。本文将在此基础上,进一步解析第六阶段的关键概念和技术实践,帮助读者深化对Java高级特性的理解和应用。通过具体的代码示例和实际项目中的应用场景,我们将探讨如何高效地利用这些特性解决复杂问题,提升开发效率和代码质量。 ... [详细]
  • Android数组截取技巧及JNI数组交互在仓库构建中的应用分析
    在Android开发中,数组截取技巧和JNI数组交互在仓库构建中的应用具有重要意义。JNI提供了两种主要的数组处理方法:一是生成原生层数组的副本,二是直接通过数组指针进行操作。在进行字符串处理时,如果需要执行其他复杂操作,可以结合这两种方法以提高效率和灵活性。此外,合理利用这些技术可以显著提升应用程序的性能和稳定性。 ... [详细]
  • 力扣——两数之和JAVA
    图片中的方法仅为个人理解,欢迎各位在下方评论 packagecom.shengda.Demo0Likou;importjava.util.HashMap; impor ... [详细]
  • 在Java NIO中,`ByteBuffer` 的内存分配方式分为 `allocate` 和 `allocateDirect`。前者在JVM堆内存中分配空间,返回 `HeapByteBuffer` 实例,初始位置为0,容量和限制由参数指定。而 `allocateDirect` 则在操作系统本地内存中分配,返回 `DirectByteBuffer`,适用于需要频繁与I/O操作交互的场景,性能更高但管理成本较大。两者在内存管理和性能上各有优劣,选择时需根据具体应用场景权衡。 ... [详细]
  • 本文详细介绍了在Windows操作系统上使用Python 3.8.5编译支持CUDA 11和cuDNN 8.0.2的TensorFlow 2.3的步骤。文章不仅提供了详细的编译指南,还分享了编译后的文件下载链接,方便用户快速获取所需资源。此外,文中还涵盖了常见的编译问题及其解决方案,确保用户能够顺利进行编译和安装。 ... [详细]
  • 1packageFileOperation;23importjava.io.File;4importjava.io.FileFilter;5importjava.util.Arra ... [详细]
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社区 版权所有