Java并发编程学习1-并发简介

简介: 本篇介绍并发简介,带大家走近Java并发编程的世界

java-concurrency-logo.png

简介

在早期的计算机中不包含操作系统,它们从头到尾只执行一个程序,并且这个程序能访问计算机中的所有资源。在这种裸机环境中,不仅很难编写和运行程序,而且每次只能运行一个程序,这对于昂贵并稀有的计算机资源来说也是一种浪费。

操作系统的出现使得计算机每次能运行多个程序,并且不同的程序都在单独的进程中运行:操作系统为各个独立执行的进程分配各种资源,包括内存,文件句柄以及安全证书等。如果需要的话,在不同的进程之间可以通过一些粗粒度的通信机制来交换数据,包括:套接字、信号处理器、共享内存、信号量以及文件等。

上世纪60年代,在操作系统中一直都是以进程作为能独立运行的基本单位。然而随着计算机技术的发展,进程慢慢出现了很多弊端,一是由于进程是资源拥有者,创建、撤消与切换存在较大的时空开销;二是由于对称多处理机(SMP)出现,可以满足多个运行单位,而多个进程并行开销过大。为了最大程度提高系统运行的性能,人们在80年代又提出了比进程更小的能独立运行的基本单位 — 线程

如果说,在操作系统中引入进程的目的,是为了使多个程序并发执行,以改善资源利用率及提高系统的吞吐量;那么,在操作系统中再引入线程则是为了减少程序并发执行时所付出的时空开销,使操作系统具有更好的并发性。

线程是Java语言中不可或缺的重要功能,它们能使复杂的异步代码变得更简单,从而极大地简化复杂系统的开发;线程会共享进程范围内的资源,例如内存句柄和文件句柄,但每个线程都有各自的程序计数器、栈以及局部变量等。线程还提供了一种直观的分解模式来充分利用多处理器系统中的硬件并行性,而在同一个程序中的多个线程也可以被同时调度到多个CPU上运行。

fleatools.png

线程的优势

如果使用得当,线程可以有效地降低程序的开发和维护等成本,同时提升复杂应用程序的性能。线程能够将大部分的异步工作流转换成串行工作流,因此能更好地模拟人类的工作方式和交互方式。此外,线程还可以减低代码的复杂度,使代码更容易编写、阅读和维护。

发挥多处理器的强大能力

多线程程序可以同时在多个处理器上执行。如果设计正确,多线程程序可以通过提高处理器资源的利用率来提高系统吞吐率。在多线程程序中,如果一个线程在等待I/O操作完成,另一个线程可以继续运行,使程序能够在I/O阻塞期间继续运行。

建模的简单性

通过使用线程,可以将复杂并且异步的工作流进一步分解为一组简单并且同步的工作流,每个工作流在一个单独的线程中运行,并在特定的同步位置进行交互。

异步事件的简化处理

服务器应用程序在接受来自多个远程客户端的套接字连接请求时,如果为每个连接都分配其各自的线程并且使用同步I/O,那么就会降低这类程序的开发难度。如果每个请求都拥有自己的处理线程,那么在处理某个请求时发生的阻塞将不会影响其他请求的处理。

响应更灵敏的用户界面

传统的GUI应用程序通常都是单线程的,在代码的各个位置都需要调用poll方法来获得输入事件或者通过一个“主事件循环(Main Event Loop)”来间接地执行应用程序的所有代码。如果在主事件循环中调用的代码需要很长时间才能执行完成,那么用户界面就会“冻结”,只有当执行控制权返回到主事件循环后,才能处理后续的用户界面事件。如果将长时间运行的任务放在一个单独的线程中运行,事件线程就能及时地处理界面事件,从而使用户界面具有更高的灵敏度。在现代的GUI框架中,例如 AWT 和 Swing 等工具,都采用一个事件分发线程(Event Dispatch Thread,EDT)来替代主事件循环。

线程的风险

安全性问题

线程安全性可能是非常复杂的,在没有充足同步的情况下,多个线程中的操作执行顺序是不可预测的,甚至会产生奇怪的结果。由于多个线程要共享相同的内存地址空间,并且是并发执行,因此它们可能会访问或修改其他线程正在使用的变量。当多个线程同时访问和修改相同的变量时,将会在串行编程模型中引入非串行因素,而这种非串行性是很难分析的。要使多线程程序的行为可以预测,必须对共享变量的访问操作进行协同,这样才不会在线程之间发生彼此干扰。

活跃性问题

安全性的含义是“永远不发生糟糕的事情”,而活跃性则关注于“某件正确的事情最终会发生”。当某个操作无法继续执行下去时,就会发生活跃性问题。后续的笔记中会慢慢介绍各种形式的活跃性问题,以及如何避免这些问题,包括死锁,饥饿,以及活锁。

性能问题

与活跃性问题密切相关的是性能问题。性能问题包括多个方面,例如服务时间过长,响应不灵敏,吞吐率过低,资源消耗过高,或者可伸缩性较低等。

结语

Java并发编程的学习注定是个枯燥的过程,为了结合实战学习并发编程,笔者推荐目前正在学习的这本《Java并发编程实战》。笔者整理这一系列的初衷是打算能够通过写博的方式,巩固当前所学的并发编程知识,如果在这个过程中能够帮助到正在学习并发编程的小伙伴,那也算是一件值得开心的事情。相信有交流、有总结的学习过程,就不会那么的枯燥无聊了。那么下一篇我们开始了解线程安全性的相关基础知识。

目录
相关文章
|
12天前
|
Java 调度 开发者
Java线程池ExecutorService学习和使用
通过学习和使用Java中的 `ExecutorService`,可以显著提升并发编程的效率和代码的可维护性。合理配置线程池参数,结合实际应用场景,可以实现高效、可靠的并发处理。希望本文提供的示例和思路能够帮助开发者深入理解并应用 `ExecutorService`,实现更高效的并发程序。
30 10
|
14天前
|
Java 数据库连接 数据库
【潜意识Java】深度分析黑马项目《苍穹外卖》在Java学习中的重要性
《苍穹外卖》项目对Java学习至关重要。它涵盖了用户管理、商品查询、订单处理等模块,涉及Spring Boot、MyBatis、Redis等技术栈。
43 4
|
14天前
|
前端开发 Java 数据库连接
【潜意识Java】深度解读JavaWeb开发在Java学习中的重要性
深度解读JavaWeb开发在Java学习中的重要性
24 4
|
14天前
|
存储 移动开发 算法
【潜意识Java】Java基础教程:从零开始的学习之旅
本文介绍了 Java 编程语言的基础知识,涵盖从简介、程序结构到面向对象编程的核心概念。首先,Java 是一种高级、跨平台的面向对象语言,支持“一次编写,到处运行”。接着,文章详细讲解了 Java 程序的基本结构,包括包声明、导入语句、类声明和 main 方法。随后,深入探讨了基础语法,如数据类型、变量、控制结构、方法和数组。此外,还介绍了面向对象编程的关键概念,例如类与对象、继承和多态。最后,针对常见的编程错误提供了调试技巧,并总结了学习 Java 的重要性和方法。适合初学者逐步掌握 Java 编程。
39 1
|
27天前
|
自然语言处理 Java 关系型数据库
Java mysql根据很长的富文本如何自动获取简介
通过使用Jsoup解析富文本并提取纯文本,然后根据需要生成简介,可以有效地处理和展示长文本内容。该方法简单高效,适用于各种应用场景。希望本文对您在Java中处理富文本并生成简介的需求提供实用的指导和帮助。
55 14
|
2月前
|
存储 缓存 Java
Java 并发编程——volatile 关键字解析
本文介绍了Java线程中的`volatile`关键字及其与`synchronized`锁的区别。`volatile`保证了变量的可见性和一定的有序性,但不能保证原子性。它通过内存屏障实现,避免指令重排序,确保线程间数据一致。相比`synchronized`,`volatile`性能更优,适用于简单状态标记和某些特定场景,如单例模式中的双重检查锁定。文中还解释了Java内存模型的基本概念,包括主内存、工作内存及并发编程中的原子性、可见性和有序性。
Java 并发编程——volatile 关键字解析
|
28天前
|
自然语言处理 Java 关系型数据库
Java mysql根据很长的富文本如何自动获取简介
通过使用Jsoup解析富文本并提取纯文本,然后根据需要生成简介,可以有效地处理和展示长文本内容。该方法简单高效,适用于各种应用场景。希望本文对您在Java中处理富文本并生成简介的需求提供实用的指导和帮助。
39 9
|
2月前
|
存储 JavaScript Java
Java 中的 String Pool 简介
本文介绍了 Java 中 String 对象及其存储机制 String Pool 的基本概念,包括字符串引用、构造方法中的内存分配、字符串文字与对象的区别、手工引用、垃圾清理、性能优化,以及 Java 9 中的压缩字符串特性。文章详细解析了 String 对象的初始化、内存使用及优化方法,帮助开发者更好地理解和使用 Java 中的字符串。
Java 中的 String Pool 简介
|
2月前
|
算法 Java 调度
java并发编程中Monitor里的waitSet和EntryList都是做什么的
在Java并发编程中,Monitor内部包含两个重要队列:等待集(Wait Set)和入口列表(Entry List)。Wait Set用于线程的条件等待和协作,线程调用`wait()`后进入此集合,通过`notify()`或`notifyAll()`唤醒。Entry List则管理锁的竞争,未能获取锁的线程在此排队,等待锁释放后重新竞争。理解两者区别有助于设计高效的多线程程序。 - **Wait Set**:线程调用`wait()`后进入,等待条件满足被唤醒,需重新竞争锁。 - **Entry List**:多个线程竞争锁时,未获锁的线程在此排队,等待锁释放后获取锁继续执行。
74 12
|
2月前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
190 2