栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java 并发 深入-5 任务执行

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java 并发 深入-5 任务执行

0. 好想做个 哥布林

为了写出并发性能更加“隽永”的代码,我们需要厘清并组织好任务的逻辑关系:
首先我们将任务抽象成 离散的工作单元
然后将多个任务组织成程序的结构
再根据自然事务(其实就是业务需求)的边界情况来处理错误(超时等等)恢复过程
最后在一些地方使用并行的计算来提升并发性
(总之,本章就是阐述 任务执行框架&任务设计思想)

1. 在线程中执行任务

从任务设计的角度思考(比如说服务器无法预料到请求到达的情况),因为自然会想将任务设计得相互独立,这样可以获得更好的调度、更容易负载均衡,最终实现高吞吐、快速响应的美好愿望。因此,这段废话的意思就是说 我们得从思考并得到清晰的 任务边界(说破了就是线程的最小粒度,但这里我们先配合一波作者) 出发来解决问题。

以web服务器应用为例,这些应用大多都会自然而然的选择一种任务边界——以独立的客户请求为边界。

于是,我们开始了拿手的极端思考方式:

1.1 串行地执行任务(就一条线程梭哈到底)

存在一些问题:
网络波动(程序难以控制的)、SocketIO(将带来阻塞)、本身就不能避免的计算(还不排除这是个大运算的情况)、阻塞后面来的请求。

这样串行的执行很容易带来 低吞吐、灵敏性拉跨的响应、服务器资源利用率感人(CPU在IO阻塞期间将空闲)

在某些情况下,串行处理方式能带来简单性或安全性(GUI就这么搞的)

1.2 显式地为任务创建线程(为每个任务分配一条线程)

主线程不断地交替指向"接受外部连接"(SocketIO)、“分发请求”(dispatch),然后循环创建新线程来处理请求。

可以得到一下推论:
将任务处理从主线程中剥离 => 减少了对后面来的请求的阻塞
并发地处理任务 => 更好的CPU利用率
任务处理的代码会被并发调用 => 必须保证其线程安全性

这种方法可以替代串行执行,并且提升性能的前提是:请求到达速率不超过服务器对请求的处理能力。

1.3 无限制创建线程的不足

前者存在的缺陷:

线程生命周期的开销非常高,因为线程的创建过程需要JVM、操作系统(这将导致不同平台的开销不同)提供一些辅助操作,大多服务器应用的请求处理的开销 较 线程创建而言,都是轻量级的。

资源消耗,活跃的线程会消耗系统资源,尤其是内存。如果可运行的线程数量多于可用处理器的数量,那么有些线程将闲置,这些闲置的线程会占据许多内存,也给后面的垃圾回收器带来压力,而且大量的线程还会增加CPU资源的竞争(同时会带来其他的开销)

稳定新,在可创建线程的数量上存在一个限制,这个限制值随平台的不同而不同,并且受到多个因素的制约:JVM启动参数、Thread构造函数中请求的栈大小以及底层操作系统对线程的限制。破坏这些限制将导致OOM,并且要像这种错误中恢复过来是非常危险的,更简单的办法是避免超出这些限制。

在一定范围内,增加线程可以提供系统的吞吐率,超出这个范围,再创建线程只会降低程序的执行速度,甚至导致应用程序崩溃。

如果服务器需要提供高可用性,并且在高负载情况下能平缓地降低性能,那么过多的创建线程将成为严重的故障。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/704163.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号