为什么java抗并发_用最通熟易懂的话说明,为什么要使用java并发编程

老早之前的计算机只有一个处理器,而 一个处理器在同一时刻只能处理一条指令 ,换句话说,我们的代码需要一行一行的按顺序被计算机执行,计算机只能把一个程序完整的执行完,然后再执行第二个程序。所以计算机专业的同学们要排队去机房做实验,一个人执行完然他的程序后,第二个人再执行自己的程序,这也就意味着 所有计算机资源是被一个程序独占的 ,计算机资源包括处理器、内存、硬盘、输入/输出设备啥的。这样的计算机系统我们称之为 裸机 。

简单批处理系统

后来人们发现对于价格高昂的计算机设备来说,在换人的过程中就浪费了好多时间,时间就是金钱,有这些时间可以多执行好多程序了。所以有人写了一个程序,把所有同学们需要做实验的程序都放在这个程序里排个队,由这个程序来协调各个同学们的程序执行,一个执行完了立即换成另一个,这样就不用人工干预了,所以他们把这样的系统叫做 简单批处理系统 ,而那个负责协调各个童鞋们程序的程序,就是所谓的 操作系统 的雏形。

多道批处理系统

我们知道,处理器的速度是嗖嗖的,比内存访问的速度快好多个数量级,而内存又比硬盘、打印机等 I/O 设备啥的快好多个数量级,而程序执行过程中又免不了从硬盘里读个文件,往打印机输出个啥的,所以 处理器浪费了好多时间等待这些I/O操作的完成 。再一次,时间就是金钱,为了尽可能的剥削计算机的运算能力,在程序遇到 I/O 操作或者什么其他会阻塞程序执行的操作时,处理器会转向执行其它的程序,什么时候这个阻塞的操作完成了,再掉过头继续执行它。从宏观上看, 处理器可以各个程序轮流执行,所以这样的系统就称为 多道批处理系统 。

分时处理

有的同学对排队执行程序这个事儿很有意见,大家都是学生,凭啥先执行你的后执行我的,你要是写了个 while(true) ,那大家都得玩儿完~所以人们给 每个程序都分配一点处理器时间去轮流执行,每个程序分配到的执行时间就叫做 时间片 ,这个过程也叫做 分时处理 。又因为处理器速度太快了, 时间片 的大小可以做到微秒毫秒的大小,所以这个切换的过程对于人来说根本感觉不出来, 所以看起来像各个程序在同时执行 。不过后来人们在一台计算机上又装了多个处理器,就是我们常听说的 4核 、 8核 啥的,所以也可能真正的在同时执行。

而 时间片 具体设置为多大,处理器怎么切换各个程序的执行,这些工作就是所谓的 操作系统来控制的。

进程

进程的概念和特点

我们自己写的程序,也就是所谓的 用户程序 是由操作系统来管理的,人们把一个 执行着的程序 叫做一个 进程 (英文名: Process ),每个 进程 都有这么两个特点:

资源所有权

程序在运行过程中需要一定的资源,比如内存、 I/O 啥的,这些东西不能在不同进程间共享,假如一个进程占了另一个进程的内存,那另一个进程的数据不就丢失了么;一个进程正在使用打印机输出东西,另一个进程也使用的话,不就尴尬了么。所以进程所拥有的这些资源是不能共享的,而这种资源分配的活是由 操作系统 来管理的。

调度/执行

操作系统 会为它管理的进程分配 时间片 ,来调度哪个进程应该被处理器处理,哪个应该先休息一会儿。

所以我们现在电脑里每个运行着的程序都是一个进程,可以打开你的任务管理器( windows )或者活动监视器( mac ),看到我们的电脑里其实有好多好多进程喔,什么QQ、微信、音乐播放器、视频播放器啥的。

进程的状态

在操作系统级别上,进程根据它运行的情况,可以分成下边5种状态 :

新建

刚刚创建的那个时刻, 操作系统 会为这个进程在内存中创建相应的数据,比如分配这个进程的ID,优先级什么的~这个状态持续的时间比较短。

就绪

一旦该进程相关的一些数据创建好了,这个进程就会被放在一个叫 就绪队列 的队列里,之后操作系统就会从这个队列里挑一个进程放到处理器里执行。

运行

这个进程被 操作系统 分配了时间片,处理器开始执行它。

阻塞

在执行进程的过程中,可能遇到某些阻塞的动作,比如 I/O 操作,处理器如果一直等待该阻塞动作完成的话就太浪费时间了,所以会把等待阻塞动作完成的进程放到一个叫 阻塞队列 的队列里,之后并不会从这个队列里挑选即将执行的进程,而是直到该阻塞动作完成,才重新把该进程放到 就绪队列 里等待执行。

退出

该进程执行完毕,或者遇到了什么错误,或者操作系统就是想弄死它,它就被杀死了,这个状态里操作系统可能还会记录一下死因啥的,这个过程也很短。

这些状态的具体转换过程看下图:

503aa5bb8209

串行编程和并行编程

到目前为止,我们的编程模式都是 串行编程 ,也就是处理器执行完一条指令再执行另一条。举个例子啊,比如你妈给你布置了两个 任务 :一是去打瓶酱油,二是去烧一壶水,按照 串行编程的方式就是两个任务依次进行,也就是说你先打酱油,然后回来再烧水。这么做没啥问题,但是没有效率啊,所以你也可以先把水烧上,然后去打酱油,回来正好水烧开了~这种 多个任务同时进行的编程方式就叫做 并行编程 。

回到计算机中来, 串行编程 的方式就是我们把所有要完成的任务放到一个 进程 中去执行,而 并行编程 的方式就是我们去开几个 进程 同时执行(注:这个 同时 可能是假的,如果只有单个处理器,那就是看上去是 同时 的)。这种 并行编程 的优势是显而易见的:

充分利用多个处理器

现代计算机的处理器越来越多,不用白不用。如果所有的任务都塞到1个进程中,而计算机实际有100个处理器,那么将会有99%的计算能力将被浪费。

防止任务的阻塞

即使是在单个处理器中,为多个任务创建多个进程也是有好处的。先执行的任务可能会需要执行某些 I/O 操作而造成阻塞,所以就需要等待 I/O 操作完成才能继续执行。但是如果为每个任务创建一个进程之后,一个任务阻塞掉并不会影响别的任务的正常执行。

简化编程的模型

把一个大任务拆分成若干个小任务自然是会事情清晰许多(注:也不是绝对啊),也就是所谓的大事化小,小事化了~所以把各个任务分配到不同进程里去执行在我们编程方面也会容易一些(注:不是绝对啊)。

线程

线程的概念

进程 是个好东西,可以给每个任务都分配一个进程以达到并发执行的目的。可是运行了一段时间人们发现还是有一些不好的地方的:

不同进程之间的资源不能够共享。

这个对于为了一个大目标细分成的若干小任务很不友好。比方说对于一个网站来说,针对每一个访问网站的连接都去创建一个进程,如果我们想累加一下总的访问连接数就比较麻烦了,因为各个进程不能去修改同一块内存。

创建、切换、销毁进程成本太大。

小贴士: 由于我们的主题是java语言里的并发操作,至于操作系统底层对于创建、切换、销毁进程都要做哪些东西不是我们唠叨的范围,但是这些操作的开销真的很大,你知道这一点就好了~

再返回头来看 进程 的两个特点,一是对资源的所有权,二是可以作为操作系统调度和执行的单位,这两个特点是没有关系的,也就是说独立的,现代的好多操作系统已经把这两个特点给拆开了, 可以被调度和执行的单位通常被称作 线程 或者 轻量级进程 ,而拥有资源所有权的单位通常被称为 进程 。

小贴士: 由于历史原因,原先的`进程`既是资源的分配单位,也是调度和执行的单位,所以我们打开一个程序就相当于打开一个进程。 提出`线程`概念之后,这种`打开一个程序就相当于打开一个进程`的叫法也被保留了下来。其实现在打开一个程序的意思是`打开一个进程并且打开若干个于这个进程相关联的线程`。

线程的特点

看一下这个 线程 的各种特点

一个进程至少对应一个线程

操作系统每开始执行一个程序,都会为其分配所需的资源以及创建若干个 程序执行流 ,也就是说会创建一个线程以及若干线程。

各个 线程 可以共享同一个进程中的各种资源

因为 线程 是从属于某个进程,所以进程中的内存、 I/O 啥的资源这个 线程 都可以访问到。接着上边那个例子,我们可以对于每一个连到网站的连接都可以分配一个线程,然后在申请一块儿内存表示连接数,每创建一个线程都把连接数加1,问题就愉快的解决了。

创建、切换、销毁线程的成本远低于原先进程的成本

因为只是一个调度和执行的单位,本来就是原先进程概念的一部分,所以创建、切换、销毁线程的成本就小多了。

线程通信比进程通信的效率高

原先进程间通信需要配合各种机制,现在线程间由于可以共享内存,所以通信就easy多了。

小贴士: 至于进程间需要啥机制我这就不说了,不是我们讨论的范围。

所以 线程 的提出完美的解决了一开始提出的把不同任务分配给不同进程执行的缺陷,现在我们可以把不同的任务分配给不同的 线程 去执行,不仅可以方便通信交流,而且创建和使用的成本还低~

线程的状态

由于线程只是单纯的继承了线程中调度和执行的特性,所以原先进程拥有的状态,现在线程一样拥有,也就是: 创建 、 就绪 、 执行 、 阻塞 、 退出 。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

不同坐标系下角速度_最伟大的数学发明,坐标系的诞生,是人类史上的方向盘...

【想要了解更多精彩文章、视频,欢迎关注创鹏科学堂】人生最大的意义,莫过于过得更方便;数学最大的意义,莫过于帮助人类过得更方便。几千年来,自从数学出现之后,它就一直以人类生活为导向,以宇宙…

php中的ol标签,html5中ol标签的用法详解

这篇文章主要介绍了详解HTML5中ol标签的用法,是HTML5入门学习中的基础知识,需要的朋友可以参考下定义和用法标签定义有序列表。HTML 4.01 与 HTML 5 之间的差异在 HTML 4.01 中,不赞成使用 "start" 属性,在 HTML 5 中是允许的。在 HTML 4.01 中…

portlet_平台策略:从Portlet到OpenSocial小工具再到渐进式Web应用程序:最新技术

portlet介绍 由于世界仍在Java的掌控之中,因此我们经常定义所谓的基于组件的平台 。 我在2000年拥有OpenUSS(开放大学支持系统)的经验。 当时我有一个想法,就是开发一个可以使用组件体系结构和J2EE技术​​( OpenUSS C…

keil5函数 默认返回值_C++ 函数的定义

“ C对于函数的基本用法”01—函数的定义//函数声明:[返回值类型] [函数名称] (参数列表)int Function(int a, int b);//函数定义int Function(int a, int b){ //函数体 return a b;}02—函数的默认参数定义函数时可以在参数列表中为形参指定默认值int Function2…

已经创建了AWS EC2实例,Linux系统默认没有root用户,那么如何创建root用户并更改为root用户登录呢?

文章目录1. 如何创建ROOT及设置密码2.更改登陆方式,采用ROOT用户登陆a. 编辑EC2实例的ssh登录方式b. 再编辑authorized_keys文件,将ssh-rsa 前面的文字全部删除,确保ssh-rsa没有任何文字,包括空格。3. 重新登陆对于刚创建AWS EC2实…

输入一个正整数求所有素数因子_一起来聊聊素数的两个性质

素数(prime number),又称质数,有无限个。定义:在大于1的自然数中,除了1和它本身以外不再有其他因数。来介绍两个简单的性质:质数的个数是无穷的。欧几里得的《几何原本》曾有一经典证明,用的是反证法。当然…

基于docker微服务架构_使用基于微服务的流架构更好地进行大规模的复杂事件处理(第1部分)...

基于docker微服务架构基于微服务的流架构与开源规则引擎相结合,使实时业务规则变得容易 这篇文章旨在详细介绍我将OSS业务规则引擎与Kafka风格的现代流消息传递系统集成在一起的项目。 该项目的目标(即众所周知的复杂事件处理(CEP&#xff0…

php怎样下载网上的文件,php怎样实现文件下载

用head() 和 fread()函数把文件直接输出到浏览器。具体代码&#xff1a;<?php $file_name "down";$file_name "down.zip"; //下载文件名$file_dir "./down/"; //下载文件存放目录//检查文件是否存在if (! file_exists ( $file_dir . $fil…

Windows 系统下,移动硬盘无法识别怎么修复?

方案1&#xff1a;移动硬盘没有驱动器号 有时移动硬盘插入计算机&#xff0c;但无法在我的计算机上显示。此时&#xff0c;可能只是因为移动硬盘没有驱动器号。 右键单击此计算机&#xff08;计算机&#xff09;&#xff0c;然后单击[管理]将其打开。 点击左边的[磁盘管理]&a…

欢乐鼠标自动点击器_使用ESP32 DIY蓝牙自动点击器,滑屏器

前言因为爱薅羊毛&#xff0c;然后正好最近免费车一趟接一趟&#xff0c;咪咕开完&#xff0c;京东开&#xff0c;京东开完掌阅开&#xff0c;下一个不知道是谁&#xff0c;&#xff0c;&#xff0c;&#xff0c;可我又不是什么很有耐心的人&#xff0c;虽然我喜欢看书&#xf…

java单词按字典排序_最终Java日志字典:开发人员最常记录的单词是什么?

java单词按字典排序最终的记录字典&#xff0c;或者&#xff1a;我们记录的最常见单词是什么&#xff1f; 日志文件是调试应用程序的最常用方法&#xff0c;当解决错误时&#xff0c;它们肯定可以引导我们朝正确的方向发展。 但是&#xff0c;大多数日志文件每天都会增加一百万…

winscp使用密钥登录远程linux系统

说明&#xff1a; WinSCP是一个Windows环境下使用SSH的开源图形化SFTP客户端。同时putty也是一个开源连接ssh的windows客户端&#xff0c;本文介绍puttyWinSCP密钥对登录linux服务器。 1. 创建密钥对 安装openssl yum –y install openssl #openssl一般服务器都会预装 创建密…

php api 实例maccms,苹果cmsV10API接口说明

api接口仅供提供数据&#xff0c;可以直接在苹果CMS后台联盟采集中加入-并提供给他人采集。联盟资源分配唯一标识ID&#xff0c;用来区别绑定分类&#xff0c;这个ID一般由苹果CMS官方提供&#xff0c;不可随意修改设置&#xff0c;否则造成入库分类错乱。视频接口同时支持老板…

dml语句包括哪些_聊聊MySQL基本操作DDL,DML,DQL,DCL

本篇文章来回顾一下MySQL的基本操作之DDL&#xff0c;DML&#xff0c;DQL&#xff0c;DCL&#xff0c;每种操作都有各自不同的语法&#xff0c;常用的操作汇总如下。一、DDL-数据定义语言作用&#xff1a;数据定义语言主要用来定义数据库中的各类对象&#xff0c;包括用户、库、…

Windows 系统下使用 putty 客户端通过 SSH 远程连接 AWS 服务器

找到在购买亚马逊的AWS服务器时保存的密钥文件&#xff08;假设为abc.pem&#xff09;。 打开PuTTYgen&#xff0c;如下图&#xff0c;点击图中1处的“load”,找到abc.pem文件所在的位置&#xff0c;并选择abc.pem&#xff0c;确定&#xff1b; 然后&#xff0c;选择图中2处…

ip integrator_使用Oracle Data Integrator(和Kafka / MapR流)完善Lambda体系结构

ip integrator“ Lambda体系结构是一种数据处理体系结构&#xff0c;旨在通过利用批处理和流处理方法来处理大量数据。 这种体系结构方法尝试通过使用批处理提供批处理数据的全面而准确的视图&#xff0c;同时使用实时流处理提供在线数据的视图来平衡延迟 &#xff0c; 吞吐量和…

php 如何获取函数类型,PHP如何使用gettype()函数判断变量的类型?

gettype()函数是PHP中的一个内置函数&#xff0c;用于获取变量的类型&#xff1b;它可用于检查现有变量的类型。下面本篇文章就来给大家介绍一下gettype()函数&#xff0c;希望对大家有所帮助。【视频教程推荐&#xff1a;PHP教程】基本语法string gettype ( $var )参数&#x…

qfile 创建文件_Qt之二进制文件读写

点击上方“Qt学视觉”&#xff0c;选择“星标”公众号重磅干货&#xff0c;第一时间送达想要学习的同学们还请认真阅读每篇文章&#xff0c;相信你一定会有所收获除了文本文件之外&#xff0c;其他需要按照一定的格式定义读写的文件都称为二进制文件&#xff0c;每种格式的二进…

iis开启php验证码,php结合GD库实现中文验证码的简单方法

前言上一次写了一个常见的验证码&#xff0c;现在玩一下中文的验证码&#xff0c;顺便升级一下写的代码流程基本差不多先看GD库开启了没生成中文5位验证码开始画图画干扰素生成图形完事生成中文验证码//小小心机$hanzi "如果觉得写得还可以的话互相关注报团取暖交流经验来…