Java 并发编程(一):简介

article/2025/11/7 13:25:33

这篇文章的标题原本叫做——Java 并发编程(一):简介,作者名叫小二。但我在接到投稿时觉得这标题不够新颖,不够吸引读者的眼球,就在发文的时候强行修改了标题(也不咋滴)。

小二是一名 Java 程序员,就职于沉默公司,工龄是两年零一个月零三天。和刚毕业那会相比,编程能力已经大有提升,但领导老王一直没敢把并发编程的开发安排给小二,这让小二心里耿耿于怀。

这事不怪老王,小二心里很清楚:编写正确的程序很难,编写正确的并发程序更是难上加难。自己功力还不到那个份上,万一搞砸了,难免让一向谨慎的老王面上无光。

小二想来想去,办法只有一个,主动去学!就找老王要了一本《Java并发编程实战》,据说这本书是并发编程中的经典之作。拿到书后,随手翻了翻,竟然发现里面藏着一封情书:小二激动坏了,想象着老王写情话的样子,不由得笑出来声。

(戛然而止)

小二的背景就先介绍到这。接下来,我们来一起鉴赏下小二读完这本书后写下的第一篇文章。

Java 并发编程(一):简介

01、为什么需要操作系统

我喜欢在写文章(不用纸和笔用电脑了)的时候听音乐(不用 MP3 用电脑了),假如电脑只能做一件事情的话,我就只能在写完文章的时候再听音乐,或者听完音乐的时候再开始写作,这样就很不爽——在没有操作系统前,的确就是这么不爽。

有了操作系统后,情况就变得大不一样了,电脑可以同时运行多个程序。通过 TOP 命令可以查看电脑上当前正在运行的进程(和程序有着密切的关系),见下图。

通常情况下,一个程序会至少对应一个进程。上图中,“Google Chrome”这三个进程意味着我的电脑上打开着一个名叫谷歌浏览器的程序。

让我们用一段专业的术语来描述一下程序和进程之间的关系:

程序是计算机为完成特定任务所执行的指令序列。 操作系统允许多道程序并发执行共享系统资源,而程序在并发执行时所产生的一系列特点使得传统的程序概念已经不足以对其进行描述,因此,引入了“进程(Process)”:可以更好的描述计算机程序的执行过程,反映操作系统的并发执行、资源共享及用户随机访问的特性,并以此作为资源分配的基本单位。

每当一个程序运行时,操作系统就为该程序创建了一个进程,并为它分配资源、调度其运行。程序执行结束后,进程也就消亡了。一个程序被同时执行多次,系统就会创建多个进程。因此,一个程序可以被多个进程执行,一个进程也可以同时执行多个程序。

当然了,对于现在的操作系统来说,进程并不是最小的调度单位,而是线程。线程也被称为轻量级进程。

由于同一个进程中的所有线程会共享进程的内存地址空间,因此这些线程都能访问相同的变量,如果没有明确的同步机制来协同对共享数据的访问,那么当一个线程正在使用某个变量时,另外一个线程可能同时访问这个变量,就会造成不可预测的结果。

02、多线程的优势

查看了一下,我这台电脑的物理 CPU(处理器)个数只有一个,但是核数(一块 CPU 上面能处理数据的芯片组的数量)是 4 个。

这意味着,我这台电脑能够在同一时间处理一个进程内的四个线程任务:线程 A 正在读取一个文件,线程 B 正在写入一个文件,线程 C 正在计算一个数值,线程 D 正在进行网络传输。

我们知道,进行文件读写或者网络传输通常会发生阻塞,这也是没办法的事。如果没有多线程的帮助,程序会按照顺序依次执行,也就意味着发生阻塞的时候其他任务只能干巴巴的等着,什么也做不了。

有了多线程,情况就完全不一样了,线程之间可以互不干扰,从而发挥处理器的多核能力。

说个有点让人难为情的事,我是 Eclipse 的(愚)忠实用户,至今没切换到 IDEA 阵营。在用 Eclipse 的时候经常会出现这样的情况,一个进度被另外一个卡住,下一个必须等待上一个执行完毕才开始执行。等待的时候几乎什么也干不成,点了取消也没用!

假如 Eclipse 采用多线程的话,每个任务放在单独的任务中执行,响应就会快很多。

03、多线程带来的风险

曾有这样一则耳熟能详的故事。

特洛伊人在城外的海滩上发现了一只巨大的木马,他们把它拉进了城里而不是把它烧掉或推到海里,以为这是天神给特洛伊人带来的赐福。于是,特洛伊人欢天喜地,庆祝胜利,他们跳着唱着,喝光了一桶又一桶的酒,以为希腊人被他们战败了。

而故事的结局大家也都知道了。希腊人把特洛伊城掠夺成空,烧成一片灰烬。海伦(宙斯之女,被称为“世上最美的女人”,她和特洛伊王子私奔,引发了特洛伊战争)也被墨涅依斯带回了希腊。

海伦

多线程带来了无与伦比的好处,但也潜藏了巨大的风险(就像那个木马)。其中尤为突出的就是安全性问题。

public class Unsafe {private int chenmo;public int add() {return chenmo++;}
}

上面这段代码在单线程的环境中可以正确执行,但在多线程的环境中则不能。递增运算 chenmo++ 可以拆分为三个操作:读取 chenmo,将 chenmo 加 1,将计算结果赋值给 chenmo。两个线程可能交替执行,发生下图中的情况,于是两个线程就会返回相同的结果。这也是最常见的一种安全性问题。

其次,多线程还会引发活跃性问题:线程 B 需要等待线程 A 释放它们共有的资源,而线程 A 由于一些问题导致无法释放资源,那么线程 B 就只能苦苦地等下去。

再者,多线程还会引发性能问题(设计良好的多线程当然会提高性能):当线程调度器临时挂起一个活跃中的线程转而运行另外一个线程时,就会频繁地出现上下文切换(Context Switch)——开销很大(挣得多花的也多)。

04、单核 CPU 和多核 CPU

来思考一个问题吧。假如 CPU 只有一个,核数也只有一个,多线程还会有优势吗?

闭上眼,让思维旋转跳跃会。

来看答案吧。

单核 CPU 上运行的多线程程序,同一时间只有一个线程在跑,系统帮忙进行线程切换;系统给每个线程分配时间片(大概 10ms)来执行,看起来像是在同时跑,但实际上是每个线程跑一点点就换到其它线程继续跑。所以效率不会有所提高,线程的切换反到增加了系统开销。

那多核 CPU 呢?

当然有优势了!多核需要多线程才能发挥优势(不然巧妇难为无米之炊啊),同样,多线程要在多核上才能有所发挥(好马配好鞍啊)。

多核 CPU 多线程不仅善于处理 IO 密集型的任务(减少阻塞时间),还善于处理计算密集型的任务,比如加密解密、数据压缩解压缩(视频、音频、普通数据等),让每个核心都物尽其用。

05、最后

亲爱的读者朋友们,小二投稿的第一篇文章到此就结束了。你对此感到满意吗?或者说你期待下一篇吗?

(此时的小二正在翘首以盼)


上一篇:Java:并发不易,先学会用

下一篇:如何保证共享变量的原子性?

微信搜索「沉默王二」公众号,关注后回复「免费视频」获取 500G 高质量教学视频(已分门别类)。


http://chatgpt.dhexx.cn/article/F7xH7Hju.shtml

相关文章

Java并发编程的艺术下载

本书简介 并发编程领域的扛鼎之作,作者是阿里和1号店的资深Java技术专家,对并发编程有非常深入的研究,《Java并发编程的艺术》是他们多年一线开发经验的结晶。本书的部分内容在出版早期发表在Java并发编程网和InfoQ等技术社区,得…

Java并发工具之Semaphore

一、简介 摘自《Java并发编程的艺术》一书 Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。 Semaphore一般用于流量的控制,特别是公共资源有限的应用场景。例…

Java 并发编程实战-创建和执行任务的最佳实践

若无法通过并行流实现并发,则必须创建并运行自己的任务。运行任务的理想Java 8方法就是CompletableFuture。 Java并发的历史始于非常原始和有问题的机制,并且充满各种尝试的优化。本文将展示一个规范形式,表示创建和运行任务的最简单&#x…

java并发-java并发大师

文章目录 java并发大师James GoslingDoug Lea 参考 java并发大师 聊聊java(十)Java并发大师Brain Goetz和Doug Lea 的中英文博客文章地址 参考URL: https://blog.csdn.net/weixin_33963594/article/details/92481739 James Gosling 技术大牛收割机&am…

java并发编程之 并发问题及解决方法

一、并发问题的根源 首先,我们要知道并发要解决的是什么问题?并发要解决的是单进程情况下硬件资源无法充分利用的问题。而造成这一问题的主要原因是CPU-内存-磁盘三者之间速度差异实在太大。如果将CPU的速度比作火箭的速度,那么内存的速度就…

『图解Java并发编程系列』10张图告诉你Java并发多线程那些破事

目录 线程安全问题 活跃性问题 性能问题 有态度的总结 头发很多的程序员:『师父,这个批量处理接口太慢了,有什么办法可以优化?』架构师:『试试使用多线程优化』第二天头发很多的程序员:『师父&#xff…

Java基础-并发篇

3.1. JAVA 并发知识库 3.2. JAVA 线程实现/创建方式 3.2.1. 继承 Thread 类 ​ Thread 类本质上是实现了 Runnable 接口的一个实例,代表一个线程的实例。启动线程的唯一方 法就是通过 Thread 类的 start()实例方法。start()方法是一个 native 方法,它将…

java并发总结

一、并发基础 ㅤ 1、进程与线程 ㅤ 进程 程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至 CPU,数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 I…

pytorch 图片分类,python 图片分类,resnet18 图片分类

pytorch 图片分类,python 图片分类,resnet18 图片分类,深度学习 图片分类 pytorch版本:1.5.0cu101 全部源码,可以直接运行。 下载地址:https://download.csdn.net/download/TangLingBo/12598435 网络是…

深度学习图片分类实战学习

开始记录学习深度学习的点点滴滴 深度学习图片分类实战学习 前言一、深度学习二、使用步骤1. 自建网络模型2. 进行深度学习的学习迁移 注意事项 前言 随着人工智能的不断发展,这门技术也越来越重要,很多人都开启了学习人工智能,本人开始记录…

关于图片的多标签分类(1)

最近还在处理人脸附件(眼镜,刘海,口罩,帽子)的multi-label分类。给自己普及一下常识性问题: 1)什么是multi-label分类? multi-label分类,常见一张图片中可以存在多个目…

svm实现图片分类(python)

目录 前言 knn vs. svm svm & linear classifier bias trick loss function regularization optimization 代码主体 导入数据及预处理 svm计算loss_function和梯度 验证梯度公式是否正确 比较运行时间 svm训练及预测,结果可视化 通过corss-validat…

图片分类-python

目的:做一个简易的图片分类。 使用到的算法:hog、surfsvm 图片集:cifar-10、cifar-100、stl-10、自制图片集 分类完整代码链接 使用说明: 1.cifar-10、cifar-100和stl-10直接解压 2.自制图片集文件夹结构: ├…

CNN图片分类

最近在阅读一些AI项目,写入markdown,持续更新,算是之后也能回想起做法 项目 https://github.com/calssion/Fun_AI image classify(图片分类) CNN classify dogs and cats(猫狗二分类) Tutorial(教程):https://developers.google.com/mach…

深度学习之图像分类

第一篇CSDN文章,写的不好,还请各位大佬指正。万事开头难,千里之行始于足下! 1.什么是图像分类 图像分类,核心是从给定的分类集合中给图像分配一个标签的任务。实际上,这意味着我们的任务是分析一个输入图…

关于图像分类

https://www.zhihu.com/question/57075015/answer/194397802https://www.zhihu.com/question/57075015/answer/194397802 先定义一下图像分类,一般而言,图像分类分为通用类别分类以及细粒度图像分类 那什么是通用类别以及细粒度类别呢?这里…

(一)图像分类任务介绍 Image Classification

目录 一、什么是图像分类任务?它有哪些应用场景? 二、图像分类任务的难点? 三、基于规则的方法是否可行? 四、什么是数据驱动的图像分类范式? 数据集构建 分类器设计与学习 分类器决策 五、常用的分类任务评价指…

图像分类的数据集

图像分类的数据集 1. MNIST2. Fashion-MNIST3.CIFAR-10和CIFAR-1004. Caltech 1015. ImageNet5.1 ImageNet是什么?5.2 ILSVRC 6. 各个数据集上的最新进展其他参考资料 1. MNIST MNIST数据集的一个样例 一般机器学习框架都使用MNIST作为入门,就像"He…

机器学习——图像分类

1 图像分类的概念 1.1 什么是图像分类? 图像分类,根据图像信息中所反映出来的不同特征,把不同类别的目标区分开来的图像处理方法 1.2 图像分类的难度 ●任何拍摄情 况的改变都将提升分类的难度 1.3 CNN如何进行图像分类 ●数据驱动型方法通…

图像分类算法

图像分类 参考链接1.前言2.K近邻与KMeans算法比较KNN原理和实现过程(1) 计算已知类别数据集中的点与当前点之间的距离:(2) 按照距离递增次序排序(3) 选取与当前点距离最小的k个点(4) 确定前k个点所在类别的出现频率(5) 返回前k个点出现频率最高的类别作为当前点的预…