【Java 并发编程】我们为什么要学并发编程?

我们为什么要学并发编程?

  • 1. 为什么要并发编程?
    • 1.1 面试需要
    • 1.2 性能调优
      • (1)加快响应时间
      • (2)代码模块化、异步化
      • (3)充分利用 CPU 的资源
  • 2. 并发编程的基础概念
    • 2.1 进程和线程
      • (1)进程(Process):一段程序的执行过程,操作系统资源分配的基本单位
      • (2)线程(Thread):处理器任务调度和执行的基本单位
      • (3)进程间通信有几种方式?
    • 2.2 CPU的核心数和线程数的关系
    • 2.3 上下文切换(Context switch)
    • 2.4 并发和并行
      • (1)并发
      • (2)并行

1. 为什么要并发编程?

1.1 面试需要

在这里插入图片描述

在这里插入图片描述
可以看到,在互联网大厂 Java 开发岗的并发编程属于标配。当然,在中小型企业并发编程的能力也是加分项,在工作中善用并发编程不仅能提高公司项目的使用体验,也能提升程序员在公司的技术话语权。

1.2 性能调优

(1)加快响应时间

举个栗子:北漂的程序员通勤动辄一两个小时,通勤时间大家都干什么呢?那当时是看网课提升自己或者追剧打发时间,这时大多数同学应该都会缓存视频,多线程就派上用场了:可以多个视频一起缓存下载。

再比如:日常开发中,尤其是互联网项目,作为一名 Java 程序员,总是想发设法提升方法/接口响应速度(调用一个复杂逻辑的接口,响应时间控制在 1s);在做 web 前端调优时:一般会将静态资源地址用两三个子域名去加载,每多一个子域名,浏览器在加载页面的时候就会多开几个线程去加载你的页面资源,提升网站的响应速度。

(2)代码模块化、异步化

举个栗子:电商系统中的订单履约流程:下单和给用户发短信/邮件就可以进行拆分,使之异步化,下单主流程同步执行,发送短信/邮件可以另起线程异步执行。这样既增加了异步的操作,提升了系统性能,又使程序模块化、可读性大大提升。

(3)充分利用 CPU 的资源

目前的 CPU 都是多个核心的,多核 CPU 下还使用单线程编程,不仅略显小 low,还无法发挥 CPU 多核的优势。

就如同上面举的北漂程序员喜欢在地铁上看网课、刷博客提升自己一样:在坐地铁的同时看网课、刷博客,回到家以后继续看网课、刷博客,这样你的时间就相当于有了两倍!这就是为什么有些人时间很充裕,而有些人老是说没时间的一个原因。工作也是这样,有的时候可以并发地去做几件事情,充分利用我们的时间。CPU 也是一样,也要充分利用。

当然有同学会有疑问,单核 CPU 呢?单核 CPU 一样可以利用到并发编程的好处吗?

当然可以,用我们平时常用的 QQ 之类的聊天程序来举例,当我们用 QQ 聊天时,其实程序要做好几件事,比如:接受我们的键盘输入,把输入的信息通过网络发给对方,接受对方通过网络发来的信息,把对方的信息显示在屏幕上,很多的时候,这些事情是可以同时发生的。如果程序不能利用并发编程同时处理,我们和对方的通话就只能一问一答的方式进行了。

2. 并发编程的基础概念

2.1 进程和线程

(1)进程(Process):一段程序的执行过程,操作系统资源分配的基本单位

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。@百科

(2)线程(Thread):处理器任务调度和执行的基本单位

线程(Thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。@百科

(3)进程间通信有几种方式?

同一台计算机的进程通信称为 IPC(Inter-process communication),不同计算机之间的进程通信被称为 R(mote)PC,需要通过网络,并遵守共同的协议,比如大家熟悉的 Dubbo 就是一个 RPC 框架,而 http 协议也经常用在 RPC 上,比如 SpringCloud 微服务。

大厂常见的面试题就是,进程间通信有几种方式?

  1. 管道,分为匿名管道(pipe)及命名管道(named pipe):匿名管道可用于具有亲缘关系的父子进程间的通信,命名管道除了具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。

  2. 信号(signal):信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,用于通知进程有某事件发生,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一致的。

  3. 消息队列(message queue):消息队列是消息的链接表,它克服了上两种通信方式中信号量有限的缺点,具有写权限得进程可以按照一定得规则向消息队列中添加新信息;对消息队列有读权限得进程则可以从消息队列中读取信息。

  4. 共享内存(shared memory):可以说这是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据得更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等。

  5. 信号量(semaphore):主要作为进程之间及同一种进程的不同线程之间得同步和互斥手段。

  6. 套接字(socket):这是一种更为一般得进程间通信机制,它可用于网络中不同机器之间的进程间通信,应用非常广泛。同一机器中的进程还可以使用 Unix domain socket(比如同一机器中 MySQL 中的控制台 mysql shell 和 MySQL 服务程序的连接),这种方式不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,比纯粹基于网络的进程间通信肯定效率更高。

2.2 CPU的核心数和线程数的关系

前面说过,目前主流 CPU 都是多核的,线程是 CPU 调度的最小单位。同一时刻,一个 CPU 核心只能运行一个线程,也就是 CPU 内核和同时运行的线程数是 1:1 的关系,也就是说 8 核 CPU 同时可以执行 8 个线程的代码。但 Intel 引入超线程技术后,产生了逻辑处理器的概念,使核心数与线程数形成 1:2 的关系。在我们前面的 Windows 任务管理器贴图就能看出来,内核数是 6 而逻辑处理器数是 12。

在 Java 中提供了 Runtime.getRuntime().availableProcessors(),可以让我们获取当前的 CPU 核心数,注意这个核心数指的是逻辑处理器数。

获得当前的 CPU 核心数在并发编程中很重要,并发编程下的性能优化往往和 CPU 核心数密切相关。

2.3 上下文切换(Context switch)

既然操作系统要在多个进程(线程)之间进行调度,而每个线程在使用 CPU 时总是要使用 CPU 中的资源,比如 CPU 寄存器和程序计数器。这就意味着,操作系统要保证线程在调度前后的正常执行,所以,操作系统中就有上下文切换的概念,它是指 CPU(中央处理单元)从一个进程或线程到另一个进程或线程的切换。

上下文是 CPU 寄存器和程序计数器在任何时间点的内容。

寄存器是 CPU 内部的一小部分非常快的内存(相对于 CPU 内部的缓存和 CPU 外部较慢的 RAM 主内存),它通过提供对常用值的快速访问来加快计算机程序的执行。

程序计数器是一种专门的寄存器,它指示 CPU 在其指令序列中的位置,并保存着正在执行的指令的地址或下一条要执行的指令的地址,这取决于具体的系统。

上下文切换可以更详细地描述为内核(即操作系统的核心)对 CPU 上的进程(包括线程)执行以下活动:

  1. 暂停一个进程的处理,并将该进程的 CPU 状态(即上下文)存储在内存中的某个地方;

  2. 从内存中获取下一个进程的上下文,并在 CPU 的寄存器中恢复它;

  3. 返回到程序计数器指示的位置(即返回到进程被中断的代码行)以恢复进程。

从数据来说,以程序员的角度来看, 是方法调用过程中的各种局部的变量与资源; 以线程的角度来看, 是方法的调用栈中存储的各类信息。

引发上下文切换的原因一般包括:线程、进程切换、系统调用等等。上下文切换通常是计算密集型的,因为涉及一系列数据在各种寄存器、 缓存中的来回拷贝。就 CPU 时间而言,一次上下文切换大概需要 5000~20000 个时钟周期,相对一个简单指令几个乃至十几个左右的执行时钟周期,可以看出这个成本的巨大。

2.4 并发和并行

(1)并发

并发(Concurrent):指应用能够交替执行不同的任务,比如单 CPU 核心下执行多线程并非是同时执行多个任务,如果你开两个线程执行,就是在你几乎不可能察觉到的速度不断去切换这两个务,已达到 “同时执行效果”,其实并不是的,只是计算机的速度太快,我们无法察觉到而已。

(2)并行

并行(Parallel):指应用能够同时执行不同的任务,例:坐地铁的时候可以同时坐地铁和看书,这两件事情可以同时执行。

Erlang 之父 Joe Armstrong 曾经用一张非常简单易懂的图解释了 「并发」与「并行」的区别

在这里插入图片描述

「并发」 是同学们排成两队,然而却只有一个咖啡机在工作,所以两个队列排在前面的同学交替使用咖啡机;「并行」 则是两台咖啡机分别服务两个独立的同学队列,它们同时进行,互不干扰。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/3683.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python自动发送邮件(html、附件等),qq邮箱和网易邮箱发送和回复

在python中,我们可以用程序来实现向别人的邮箱自动发送一封邮件,甚至可以定时,如每天8点钟准时给某人发送一封邮件。今天,我们就来学习一下,如何向qq邮箱,网易邮箱等发送邮件。 一、获取邮箱的SMTP授权码。…

树与二叉树的存储与遍历

文章目录一、树概念二、二叉树三、二叉树的存储与遍历一、树概念 如前面的顺序表,链表,栈和队列都是线性的数据结构,树是非线性的结构。树可以有n个结点,n>0,当n0是就表示树为空 n>0,代表树不为空,不为空的树&am…

Idea+maven+spring-cloud项目搭建系列--11 整合dubbo

前言: 微服务之间通信框架dubbo,使用netty (NIO 模型)完成RPC 接口调用; 1 dubbo 介绍: Apache Dubbo 是一款 RPC 服务开发框架,用于解决微服务架构下的服务治理与通信问题,官方提…

如果大学能重来,我绝对能吊打90%的大学生,早知道这方法就好了

最近收到很多大学生粉丝的私信,大多数粉丝们都迷茫着大学计算机该怎么学,毕业后才能找到好工作。 可能是最近回答这方面的问题有点多,昨晚还真梦回大学…其实工作了20多年,当过高管,创过业,就差没写书了。…

基于 Docker 的深度学习环境:入门篇

这篇文章聊聊如何从零到一安装、配置一个基于 Docker 容器的深度学习环境。 写在前面 这段时间,不论是 NLP 模型,还是 CV 模型,都得到了极大的发展。有不少模型甚至可以愉快的在本地运行,并且有着不错的效果。所以,经…

【数据结构】实现二叉树的基本操作

目录 1. 二叉树的基本操作 2. 具体实现 2.1 创建BinaryTree类以及简单创建一棵树 2.2 前序遍历 2.3 中序遍历 2.4 后序遍历 2.5 层序遍历 2.6 获取树中节点的个数 2.7 获取叶子节点的个数 2.8 获取第K层节点的个数 2.9 获取二叉树的高度 2.10 检测值为val的元素是否…

Fiddler抓取https史上最强教程

有任何疑问建议观看下面视频 2023最新Fiddler抓包工具实战,2小时精通十年技术!!!对于想抓取HTTPS的测试初学者来说,常用的工具就是fiddler。 但是初学时,大家对于fiddler如何抓取HTTPS难免走歪路&#xff…

使用stm32实现电机的PID控制

使用stm32实现电机的PID控制 PID控制应该算是非常古老而且应用非常广泛的控制算法了,小到热水壶温度控制,大到控制无人机的飞行姿态和飞行速度等等。在电机控制中,PID算法用的尤为常见。 文章目录使用stm32实现电机的PID控制一、位置式PID1.计…

史诗级详解面试中JVM的实战

史诗级详解面试中JVM的实战 1.1 什么是内存泄漏?什么是内存溢出?1.2 你们线上环境的JVM都设置多大?1.3 线上Java服务器内存飙升怎么回事?1.4 线上Java项目CPU飙到100%怎么排查?1.5 线上Java项目OOM了,怎么回事?1.1 什么是内存泄漏?什么是内存溢出? 内存溢出:OutOfMe…

JavaScript中的for in和for of的区别(js的for循环)

简述:js中的for循环大家都知道,今天来分享下for in和for of在使用时区别和注意事项,顺便做个笔记; 测试数据 //数组const arr [1, 2, 3, 4, 5]//对象const obj {name: "小李",color: ["plum", "pink&q…

【巨人的肩膀】JAVA面试总结(七)

💪MyBatis 1、谈谈你对MyBatis的理解 Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,加载驱动、创建连接、创建statement等繁杂的过程,开发者开发时只需要关注如何编写SQL语句,可以…

蓝桥杯C/C++VIP试题每日一练之完美的代价

💛作者主页:静Yu 🧡简介:CSDN全栈优质创作者、华为云享专家、阿里云社区博客专家,前端知识交流社区创建者 💛社区地址:前端知识交流社区 🧡博主的个人博客:静Yu的个人博客 🧡博主的个人笔记本:前端面试题 个人笔记本只记录前端领域的面试题目,项目总结,面试技…

Python 十大开源Python库,看看你熟悉几个?

嗨害大家好鸭!我是芝士❤ 对于码农来说, 关注的永远是新近有什么流行的、 既能解决问题又好用的利器。 本文就为你盘点十大开源Python库。 1、Pipenv 第一名非它莫属, 这个工具2017年初才发布, 但它已经能够影响每个Python开发…

菜鸟刷题Day7

⭐作者:别动我的饭 ⭐专栏:菜鸟刷题 ⭐标语:悟已往之不谏,知来者之可追 一.整理字符串:1544. 整理字符串 - 力扣(LeetCode) 描述 给你一个由大小写英文字母组成的字符串 s 。 一个整理好的字…

C语言番外-------《函数栈帧的创建和销毁》知识点+基本练习题+完整的思维导图+深入细节+通俗易懂建议收藏

绪论 书接上回,上回我们已经将C语言的所有知识点进行了总结归纳到同一个思维导图中,而本章是一个番外篇,将具体讲述一些更深入的知识。 话不多说安全带系好,发车啦(建议电脑观看)。 附:红色&…

我用Python django开发了一个商城系统,已开源,求关注!

起始 2022年我用django开发了一个商城的第三方包,起名为:django-happy-shop。当时纯粹是利用业余时间来开发和维护这个包,想法也比较简单,Python语言做web可能用的人比较少,不一定有多少人去关注,就当是一个…

我们在操作自动化测如何实现用例设计实例

在编写用例之间,笔者再次强调几点编写自动化测试用例的原则: 1、一个脚本是一个完整的场景,从用户登陆操作到用户退出系统关闭浏览器。 2、一个脚本脚本只验证一个功能点,不要试图用户登陆系统后把所有的功能都进行验证再退出系统…

【开发】后端框架——Dubbo

前置知识: 微服务 Dubbo是高性能的RPC框架,主要目的是支持远程调用 Dubbo Dubbo是一个 高性能和透明化的RPC框架 ,主要目的是支持远程调用,是阿里巴巴SOA服务化治理方案的核心框架 最大的特点是按照分层的方式来 架构 &#xff0c…

LDNet分割模型搭建

原论文:https://arxiv.org/abs/2110.09103源码:https://github.com/unilight/LDNet 直接步入正题~~~ 一、ESA_blcok模块 1、PPM模块 class PPM(nn.Module):def __init__(self, pooling_sizes(1, 3, 5)):super().__init__()self.layer nn.ModuleList…

蓝桥杯刷题冲刺 | 倒计时13天

作者:指针不指南吗 专栏:蓝桥杯倒计时冲刺 🐾马上就要蓝桥杯了,最后的这几天尤为重要,不可懈怠哦🐾 文章目录1.母牛的故事2.魔板1.母牛的故事 题目 链接: [递归]母牛的故事 - C语言网 (dotcpp.c…