真的还有必要学习JAVA多线程吗?

简介: 真的还有必要学习JAVA多线程吗?

🔎这里是JAVA多线程加油站
👍如果对你有帮助,给博主一个免费的点赞以示鼓励
欢迎各位🔎点赞👍评论收藏⭐️

一、忘掉那该死的并行

Linus Torvalds是一个传奇式的人物(图1.1),是他给出了Linux的原型,并一直致力于推广和发展Linux系统。1991年,他首先在网络上发布了Linux源码,从此Linux 迅速崛起壮大,成为目前使用最广泛的操作系统之一。
在这里插入图片描述

  • 自2002年起,Linus就决定使用BitKeeper作为Linux内核开发的版本控制工具,以此来维护Linux的内核源码。BitKeeper
    是一套分布式版本控制软件,它是一套商用系统,由BitMover公司开发。2005年,BitKeeper宣称发现
    Linux内核开发人员使用逆向工程来试图解析BitKeeper 内部协议。因此,决定向Linus 收回
    BitKeeper授权。虽然Linux核心团队与BitMover公司进行了协商,但是仍无法解决他们之间的分歧。因此,Linus
    决定自行研发版本控制工具来代替BitKeeper。于是,Git诞生了。
  • 如果你正在使用Git,那么我相信你一定会为Git的魅力所征服;如果你还没有了解过Git,那么我强烈建议你关注一下这款优秀的产品。
  • 而正是这位传奇人物,给目前红红火火的并行计算泼了一大盆冷水。那么,并行计算究竟应该何去何从呢?

在 Linus的发言中这么说道:

Where the hell do you envision that those magical parallel algorithms would be used?
The only place where parallelism matters is in graphics or on the server side,where we alreadylargely have it. Pushing it anywhere else is just pointless.
So the whole argument that people should parallelise their code is fundamentally flawed. It restson incorrect assumptions.It's a fad that has been going on too long.

需要有多么奇葩的想象力才能想象出并行计算的用武之地?
并行计算只能在图像处理和服务端编程两个领域使用,并且它在这两个领域确实有着大量广泛的使用。但是在其他任何地方,并行计算毫无建树!
因此,人们争论是否应该将代码并行化是一个本质上的错误。这完全基于一个错误的假设。“并行”是一个早该结束的时髦用语。

  • 看了这段较为完整的表述,大家应该对Linus 的观点有所感触,我对此也表示赞同。与串行程序不同,并行程序的设计和实现异常复杂,不仅体现在程序的功能分离上,多线程间的协调性、乱序性都会成为程序正确执行的障碍。只要你稍不留神,就会失之毫厘,谬以千里!混乱的程序难以阅读、难以理解,更难以调试。所谓并行,也就是把简单问题复杂化的典型。因此,只有“疯子”才会叫嚣并行就是未来(Thecrazies talking about scaling tohundreds of cores are just that -crazy)。
  • 但是,Linus也提出了两个特例,那就是图像处理和服务端程序是可以也需要使用并行技术的。仔细想想,为什么图像处理和服务端程序是特例呢?
  • 和用户终端程序不同,图像处理往往拥有极大的计算量。一张1024×768像素的图片,包含多达78万6千多个像素。即使将所有的像素遍历一遍,也得花不少时间。更何况,图像处理涉及大量的矩阵计算。矩阵的规模和数量都会非常大。因为如此密集的计算,很有可能超过单核CPU的计算能力,所以自然需要引入多核计算了。
  • 而服务端程序与一般的用户终端程序相比,一方面,服务端程序需要承受很大的用户访问压力。根据淘宝的数据,它在“双11”一天,支付宝核心数据库集群处理了41亿个事务,执行285亿次SQL,生成15TB日志,访问1931亿次内存数据块,发生13亿个物理读。如此密集的访问,恐怕任何一台单核计算机都难以胜任,因此,并行程序也就自然成了唯一的出路。另一方面,服务端程序往往会比用户终端程序拥有更复杂的业务模型。面对复杂业务模型,并行程序会比串行程序更容易适应业务需求,更容易模拟我们的现实世界。毕竟,我们的世界本质上是并行的。比如,当你开开心心去上学的时候,妈妈可能在家里忙着家务,爸爸在外打工赚钱,一家人其乐融融。如果有一天,你需要使用你的计算机来模拟这个场景,你会怎么做呢?如果你就在一个线程里,既做了你自己,又做了妈妈,又做了爸爸,显然这不是一种好的解决方案。但如果你使用三个线程,分别模拟这三个人,一切看起来那么自然,而且容易被人理解。
  • 再举一个专业点的例子,比如基础平台Java虚拟机,虚拟机除了要执行main函数主线程外,还需要做JIT
    编译,需要做垃圾回收。无论是main
    函数、JIT编译还是垃圾回收,在虚拟机内部都是一个单独的线程。是什么使得虚拟机的研发人员这么做的呢?显然,这是因为建模的需要。因为这里的每一个任务都是相对独立的。我们不应该将没有关联的业务代码拼凑在一起,分离为不同的线程更容易理解和维护。因此,使用并行也不完全是出于性能的考虑,而有时候,我们会很自然地那么做。

二、可怕的现实:摩尔定律的失效

  • 摩尔定律是由英特尔创始人之一戈登·摩尔提出来的,其内容为:集成电路上可容纳的电晶体(晶体管)数目,约每隔24个月便会增加一倍。经常被引用的“18个月”,是由英特尔首席执行官大卫·豪斯所说:预计18个月会将芯片的性能提高一倍(即更多的晶体管使其更快)。
  • 说得直白点,就是每18个月到24个月,我们的计算机性能就能翻一番。
  • 反过来说,就是每过18个月到24个月,你在未来用一半的价钱就能买到和现在性能相同的计算设备了。这听起来是一件多么激动人心的事情呀!
  • 但是,摩尔定律并不是一种自然法则或者物理定律,它只是基于人为观测数据对未来的预测。按照这种速度,我们的计算能力将会按照指数速度增长,用不了多久,我们的计算能力就能超越“上帝”了!畅想未来,基于强劲的超级计算机,我们甚至可以模拟整个宇宙。
  • 摩尔定律的有效性已经超过半个世纪了,然而,在2004年,Intel宣布将4GHz芯片的发布时间推迟到2005年,在2004年秋季,Intel宣布彻底取消4GHz计划(如图1.2所示)。
  • 是什么迫使世界顶级的科技巨头放弃4GHz的研发呢?显然,就目前的硅电路而言,很有可能已经走到了头。我们的制造工艺已经精确到了纳米了。1纳米是10°米,也就是十亿分之一米。这已经是一个相当小的数字了。就目前的科技水平而言,如果无法在物质分子层面以下进行工作,那么也许4GHz的芯片就已经接近理论极限了。因为即使一个水分子,它的直径也有0.4纳米。再往下发展就显得有些困难。当然,如果我们使用完全不同的计算理论或者芯片生成工艺,也许会有本质的突破,但目前还没有看到这种技术被大规模使用的可能。

在这里插入图片描述
因此,摩尔定律在CPU的计算性能上可能已经失效。虽然,现在Intel已经研制出了4GHz芯片,但可以看到,在近10年的发展中,CPU主频的提升已经明显遇到了一些暂时不可逾越的瓶颈。

三、柳暗花明:不断地前进

  • 虽然CPU的性能已经几近止步,长达半个世纪的摩尔定律轰然倒地,但是这依然没有阻挡科学家和工程师们带领我们不断向前的脚步。
    从2005年开始,我们已经不再追求单核的计算速度,而着迷于研究如何将多个独立的计算单元整合到单独的CPU中,也就是我们所说的多核CPU。短短十几年的发展,家用型CPU,比如Intel
    i7就可以拥有4核心,甚至8核心。而专业服务器则通常可以配有几个独立的CPU,每一个CPU都拥有多达8个甚至更多的内核。从整体上看,专业服务器的内核总数甚至可以达到几百个。
  • 非常令人激动,摩尔定律在另外一个侧面又生效了。根据这个定律,我们可以预测,每过18个月到24个月,CPU的核心数就会翻一番。用不了多久,拥有几十甚至上百个CPU内核的芯片就能进入千家万户。
  • 顶级计算机科学家唐纳德·尔文·克努斯(Donald Ervin
    Knuth),如此评价这种情况:在我看来,这种现象(并发)或多或少是由于硬件设计者已经无计可施导致的,他们将摩尔定律失效的责任推给软件开发者。
  • 唐纳德(如图1.3所示)是计算机巨著《计算机程序设计艺术》的作者。《美国科学家》杂志曾将该书与爱因斯坦的《相对论》、狄拉克的《量子力学》和理查·费曼的《量子电动力学》等书并列为20世纪最重要的12本物理科学类专论书之一。

在这里插入图片描述

四、光明或是黑暗

  • 根据唐纳德的观点,摩尔定律本应该由硬件开发人员维持。但是,很不幸,硬件工程师似乎已经无计可施了。为了继续保持性能的高速发展,硬件工程师破天荒地想出了将多个CPU内核塞进一个CPU里的奇妙想法。由此,并行计算就被非常自然地推广开来,随之而来的问题也层出不穷,程序员的黑暗时期也随之到来。简化的硬件设计方案必然带来软件设计的复杂性。换句话说,软件工程师正在为硬件工程师无法完成的工作负责,因此,也就有了唐纳德的“他们将摩尔定律失效的责任推给了软件开发者”的说法。
  • 所以,如何让多个CPU有效并且正确地工作也就成了一门技术,甚至是很大的学问。比如,多线程间如何保证线程安全,如何正确理解线程间的无序性、可见性,如何尽可能地设计并行程序,如何将串行程序改造为并行程序。而对并行计算的研究,也就是希望给这片黑暗带来光明。

本文参考多线程高并发程序设计,非常棒的一本书,推荐xdm学习

相关文章
|
2天前
|
存储 监控 Java
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
89 60
【Java并发】【线程池】带你从0-1入门线程池
|
13天前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
72 14
|
16天前
|
安全 Java 程序员
Java 面试必问!线程构造方法和静态块的执行线程到底是谁?
大家好,我是小米。今天聊聊Java多线程面试题:线程类的构造方法和静态块是由哪个线程调用的?构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节有助于掌握Java多线程机制。下期再见! 简介: 本文通过一个常见的Java多线程面试题,详细讲解了线程类的构造方法和静态块是由哪个线程调用的。构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节对掌握Java多线程编程至关重要。
48 13
|
17天前
|
安全 Java 开发者
【JAVA】封装多线程原理
Java 中的多线程封装旨在简化使用、提高安全性和增强可维护性。通过抽象和隐藏底层细节,提供简洁接口。常见封装方式包括基于 Runnable 和 Callable 接口的任务封装,以及线程池的封装。Runnable 适用于无返回值任务,Callable 支持有返回值任务。线程池(如 ExecutorService)则用于管理和复用线程,减少性能开销。示例代码展示了如何实现这些封装,使多线程编程更加高效和安全。
|
1月前
|
Java 调度 开发者
Java线程池ExecutorService学习和使用
通过学习和使用Java中的 `ExecutorService`,可以显著提升并发编程的效率和代码的可维护性。合理配置线程池参数,结合实际应用场景,可以实现高效、可靠的并发处理。希望本文提供的示例和思路能够帮助开发者深入理解并应用 `ExecutorService`,实现更高效的并发程序。
37 10
|
1月前
|
Java 数据库连接 数据库
【潜意识Java】深度分析黑马项目《苍穹外卖》在Java学习中的重要性
《苍穹外卖》项目对Java学习至关重要。它涵盖了用户管理、商品查询、订单处理等模块,涉及Spring Boot、MyBatis、Redis等技术栈。
122 4
|
1月前
|
前端开发 Java 数据库连接
【潜意识Java】深度解读JavaWeb开发在Java学习中的重要性
深度解读JavaWeb开发在Java学习中的重要性
38 4
|
1月前
|
存储 移动开发 算法
【潜意识Java】Java基础教程:从零开始的学习之旅
本文介绍了 Java 编程语言的基础知识,涵盖从简介、程序结构到面向对象编程的核心概念。首先,Java 是一种高级、跨平台的面向对象语言,支持“一次编写,到处运行”。接着,文章详细讲解了 Java 程序的基本结构,包括包声明、导入语句、类声明和 main 方法。随后,深入探讨了基础语法,如数据类型、变量、控制结构、方法和数组。此外,还介绍了面向对象编程的关键概念,例如类与对象、继承和多态。最后,针对常见的编程错误提供了调试技巧,并总结了学习 Java 的重要性和方法。适合初学者逐步掌握 Java 编程。
56 1
|
1月前
|
缓存 安全 算法
Java 多线程 面试题
Java 多线程 相关基础面试题
|
9月前
|
存储 安全 Java
深入理解Java并发编程:线程安全与锁机制
【5月更文挑战第31天】在Java并发编程中,线程安全和锁机制是两个核心概念。本文将深入探讨这两个概念,包括它们的定义、实现方式以及在实际开发中的应用。通过对线程安全和锁机制的深入理解,可以帮助我们更好地解决并发编程中的问题,提高程序的性能和稳定性。

热门文章

最新文章