【javaEE-有关CPU进程和线程实现的并发编程及二者的区别】

2024-06-13 12:20

本文主要是介绍【javaEE-有关CPU进程和线程实现的并发编程及二者的区别】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

🔥🔥🔥有关进程并发编程开发的成本问题

这次之前其实我们所有的写的程序都是使用单核心来运行的,但是一般我们的计算机都有很多核心,如果我们编程的时候,只使用一个核心的话,其实这是一个非常大的浪费,所以我们引进了多进程这种并发编程来充分利用计算机的多核心。但是随着我们的需求越来越大,进程的一些缺点就显现出来了。

  • 创建和销毁进程的成本很大
  • 越来越多的需求场景需要一种更方便的并发编程形式
  • 线程的出现

由此我们发明了一个新的并发编程的形式,线程(Thread),对比进程,它的创建和销毁成本更小,更轻量。因此现在的主流并发编程的形式就是多线程编程。

在这里插入图片描述

🔥🔥🔥多线程编程

对于进程来说,一个进程是由一组PCB类似于结构体的形式对数据进行描述,进一步的通过链表的形式将数据组织起来。对于线程来说,一个线程是只有有一个PCB结构的形式,所以这里就有一个包含关系:一个进程中可以包含多个线程,此时每一个线程都可以独立的在CPU上调度执行,这里我们对进程和线程做一个总结:

  • 进程是系统资源分配的基本单位
  • 线程是cpu调度执行的基本单位

一个可执行的程序,双击exe文件,系统就会创建一个进程,给这个进程中分配一些系统资源(硬盘,cpu,内存,网络带宽等)。在这个进程中会创建一个或多个线程。这些线程才在cpu中调度执行。同一个进程中的多个线程其实是共用同一份系统资源的。

对比进程,线程是更轻量的,主要是在我们创建一个进程的时候,就已经创建了一个线程了,同时就会分配系统资源,后序我们在创建第二个第三个线程的时候,就不用再分配资源了~,因此他就省去了分配资源的过程。也省去了释放资源的过程。在这里插入图片描述

🔥🔥🔥系统分析多线程调度执行过程

比如说现在有请我们最可爱的joey老铁上场,此时在一个房间里他要一个人吃完100只鸡。
在这里插入图片描述
为了提高老铁的吃鸡效率,我们可以引用多进程的概念,在创建一个房间,还是一个joey老铁,只需要吃50只鸡。
在这里插入图片描述
这样确实提高了joey吃鸡的效率,但是我们其实不难发现这种效率是非常低的,我们显然可以用一个更简单的方式提高吃鸡的效率,我们可以在一个房间里引进多个joey老铁,这样的方式不仅大大提高了吃鸡的效率,而且大大缩减了成本的损耗。这其实就是多线程的概念。相比于多进程,这种形式效率是极高的。
在这里插入图片描述

那我们就自然的想到,在引进一些线程,会不会进一步提高效率呢?当然会!!!
在这里插入图片描述
但是当我们将线程增加带一些程度的时候,就会出现问题了~
在这里插入图片描述
此时就再也无法通过增加线程的方式,提高程序执行的效率了,因为桌子的空间是有限的,我们增加多个joey后,势必会有一些joey老铁是吃不到桌子上的鸡的,即线程多了,cpu的资源是有限的,这样就无法提高效率了。

有时甚至可能会由于线程的增多,导致线程可能会争夺系统资源,最后导致系统崩溃!!!

🔥🔥🔥线程和进程的概念即区别

1. 进程包含线程: 即一个进程中可以包含一个或者多个线程,但是不能没有线程,当我们创建一个main函数时就是一个主线程。
2. 进程是系统资源分配的基本单位,线程是系统调度执行的基本单位。
3. 同一个进程中的所有线程其实是共用同一份系统资源的(硬盘,内存,网络带宽等)
4. 线程是当下实现并发编程的主流方式,通过多线程可以很好的利用cpu的多核心特性~但是并不是线程越多越好的,随着线程的增多(当然创建线程也会有一定的开销),可能会导致多个线程之间争夺系统资源,甚至导致系统的崩溃
5. 多个线程之间,其实也存在一定的安全问题,当一个线程产生异常时,可能也会影响其他线程的正常执行~
6. 多个进程之间一般是不会相互影响的,、一个进程崩溃,并不会影响其他进程的运行(这也称为“进程的隔离性”)。在这里插入图片描述

这个问题非常重要,是面试的高频问题,一定要牢记于心啊!!!

🔥🔥🔥如何在java中创建线程

线程其实是属于操作系统中的概念,操作系统会提供api,供程序员调用,但是不同的操作系统其实对应的api是不同的,java中jvm已经替我们将这些api封装好了,我们只需要关注jvm中的这一套api就好了。
一般我们通过使用Thread这个类来完成多线程的开发。

🗼🗼🗼继承Thread重写Run方法创建线程

class MyThread extends Thread{@Overridepublic void run() {System.out.println("Thread hello");}
}
public class Demo2 {public static void main(String[] args) {MyThread t=new MyThread();t.start();System.out.println("main hello");}
}

这里的run函数的主体其实就是我们完成线程主体任务的地方,在这里实现代码的主体部分,然后通过start方法,真正在内存中创建一个线程,通过回调函数run执行相关操作。回调函数就是用户手动定义了,但是没有手动调用,但是最后被系统调用的函数。

🗼🗼🗼实现Runnable创建线程

class MyRunnable implements Runnable{@Overridepublic void run() {while(true){System.out.println("hello thread");try{Thread.sleep(1000);}catch (InterruptedException e){throw new RuntimeException(e);}}}
}
public class Demo3 {public static void main(String[] args) throws InterruptedException {MyRunnable runnable=new MyRunnable();Thread t=new Thread(runnable);t.start();while(true){System.out.println("hello main");Thread.sleep(1000);}}
}

这里的sleep是Thread中的库函数,可以不导入包直接调用,但是这里存在一个受查异常,所以要进行异常捕捉。由于父类中的run方法并没有这个异常所以我们只能利用try-catch,而不能把异常向上抛出。

🗼🗼🗼继承Thread利用匿名内部类实现一个线程

public static void main(String[] args) throws InterruptedException{Thread t=new Thread(){@Overridepublic void run() {while(true){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}};t.start();while(true){System.out.println("hello main");Thread.sleep(1000);}}

匿名内部类定义在一个类的内部,只能使用一次。

🗼🗼🗼实现Runnable利用匿名内部类创建线程

public static void main(String[] args) throws InterruptedException {Thread t = new Thread(new Runnable() {@Overridepublic void run() {while (true) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}});while (true) {System.out.println("hello main");Thread.sleep(1000);}}

🗼🗼🗼利用lamda表达式创建一个线程

    public static void main(String[] args) throws InterruptedException{Thread t=new Thread(()->{while(true){System.out.println("thread hello");try{Thread.sleep(1000);}catch (InterruptedException e){throw new RuntimeException(e);}}},"自定义线程");t.start();while(true){System.out.println("hello main");Thread.sleep(1000);}}

好了,今天就分享这么多了,感兴趣的话关注不迷路哦

这篇关于【javaEE-有关CPU进程和线程实现的并发编程及二者的区别】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1057288

相关文章

SpringBoot监控API请求耗时的6中解决解决方案

《SpringBoot监控API请求耗时的6中解决解决方案》本文介绍SpringBoot中记录API请求耗时的6种方案,包括手动埋点、AOP切面、拦截器、Filter、事件监听、Micrometer+... 目录1. 简介2.实战案例2.1 手动记录2.2 自定义AOP记录2.3 拦截器技术2.4 使用Fi

最新Spring Security的基于内存用户认证方式

《最新SpringSecurity的基于内存用户认证方式》本文讲解SpringSecurity内存认证配置,适用于开发、测试等场景,通过代码创建用户及权限管理,支持密码加密,虽简单但不持久化,生产环... 目录1. 前言2. 因何选择内存认证?3. 基础配置实战❶ 创建Spring Security配置文件

Python对接支付宝支付之使用AliPay实现的详细操作指南

《Python对接支付宝支付之使用AliPay实现的详细操作指南》支付宝没有提供PythonSDK,但是强大的github就有提供python-alipay-sdk,封装里很多复杂操作,使用这个我们就... 目录一、引言二、准备工作2.1 支付宝开放平台入驻与应用创建2.2 密钥生成与配置2.3 安装ali

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、

PyCharm中配置PyQt的实现步骤

《PyCharm中配置PyQt的实现步骤》PyCharm是JetBrains推出的一款强大的PythonIDE,结合PyQt可以进行pythion高效开发桌面GUI应用程序,本文就来介绍一下PyCha... 目录1. 安装China编程PyQt1.PyQt 核心组件2. 基础 PyQt 应用程序结构3. 使用 Q

springboot自定义注解RateLimiter限流注解技术文档详解

《springboot自定义注解RateLimiter限流注解技术文档详解》文章介绍了限流技术的概念、作用及实现方式,通过SpringAOP拦截方法、缓存存储计数器,结合注解、枚举、异常类等核心组件,... 目录什么是限流系统架构核心组件详解1. 限流注解 (@RateLimiter)2. 限流类型枚举 (

Java Thread中join方法使用举例详解

《JavaThread中join方法使用举例详解》JavaThread中join()方法主要是让调用改方法的thread完成run方法里面的东西后,在执行join()方法后面的代码,这篇文章主要介绍... 目录前言1.join()方法的定义和作用2.join()方法的三个重载版本3.join()方法的工作原

Spring AI使用tool Calling和MCP的示例详解

《SpringAI使用toolCalling和MCP的示例详解》SpringAI1.0.0.M6引入ToolCalling与MCP协议,提升AI与工具交互的扩展性与标准化,支持信息检索、行动执行等... 目录深入探索 Spring AI聊天接口示例Function CallingMCPSTDIOSSE结束语

Java获取当前时间String类型和Date类型方式

《Java获取当前时间String类型和Date类型方式》:本文主要介绍Java获取当前时间String类型和Date类型方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录Java获取当前时间String和Date类型String类型和Date类型输出结果总结Java获取

Spring Boot Actuator应用监控与管理的详细步骤

《SpringBootActuator应用监控与管理的详细步骤》SpringBootActuator是SpringBoot的监控工具,提供健康检查、性能指标、日志管理等核心功能,支持自定义和扩展端... 目录一、 Spring Boot Actuator 概述二、 集成 Spring Boot Actuat