Java 并发编程实战笔记
文章平均质量分 57
艾黛尔贾特
这个作者很懒,什么都没留下…
展开
-
基于生产者-消费者模式的桌面搜索器
基于生产者-消费者模式的桌面搜索器FileCrawler 为生产者,负责在某个文件层次结构中搜索符合要求的文件,并将它们放入工作队列。Indexer 为消费者,每次从工作队列中取出一个文件并为它建立索引。结构优势生产者-消费者模式提供了一种适合线程的方法将桌面搜索问题分解为更简单的组件。将文件遍历和建立索引分解为两个独立的操作,比之放一个操作中实现有着更高的可读性和可重用性。此方式每个操作仅需完成一个独立的任务,且任务的控制流由阻塞队列全权负责。性能优势利用生产者-消费者模式,使得遍历文件原创 2021-01-10 14:40:16 · 96 阅读 · 0 评论 -
并发容器
并发容器并发容器是专门针对多线程环境下对容器并发访问设计的,并发容器还增加了对一些常见复合操作的支持,这些操作都是线程安全。使用并发容器代替同步容器,可以极大地提高程序的伸缩性、并发性以及降低风险。并发容器 <> 同步容器ConcurrentHashMap <> 同步的 HashMap、CopyOnWriteArrayListConcurrentSkipListMap <> SortedMap、TreeMapConcurrentSkipListSet原创 2021-01-10 14:34:31 · 86 阅读 · 0 评论 -
页面渲染器
页面渲染器本文将使用不同方式实现 Web 页面渲染器,并分析不同实现方式的优缺点。SingleThreadRendererSingleThreadRenderer 是一个串行页面渲染器,它先渲染绘制文本元素,同时为图像预留出矩形空间,待文本渲染完毕后开始下载图像,图像下载完后将它们渲染并绘制在相应的预留空间中。由于图像下载的过程中大部分时间在等待 I/O,而 CPU 是空闲的,浪费了计算资源。故为了获得更高的 CPU 利用率和响应性,可以将问题拆分成多个独立的任务并发执行。public class原创 2021-01-10 14:16:58 · 260 阅读 · 0 评论 -
挖掘并行性
挖掘并行性大多数服务器应用程序都存在一个明显的任务边界:单个客户请求。但有时候即便是单个请求也存在可挖掘的并行性。异构任务的并行化所带来的提升往往十分有限,只有当大量相互独立且同构的任务可以并发进行处理时,才能体现出将程序的工作负载分配到多个任务中带来的真正性能提升。...原创 2021-01-10 14:17:47 · 97 阅读 · 0 评论 -
获取任务的结果
获取任务的结果Executor 框架使用 Runnable 作为其基本的任务表现形式。如果提交的任务是一次延迟计算且我们需要获取计算的结果,只通过 Runnable 是无法实现的。原因在于其 run 方法不能返回一个值或抛出一个受查异常。可以使用 Callable 或 Future 来实现。如果向 Executor 提交一组计算任务,且希望在计算完成后获取结果,有两种方式:保留与每个任务关联的 Future,然后反复使用 get 方法,同时将 timeout 参数指定为 0,从而实现轮询判断任务是否原创 2021-01-08 20:07:17 · 362 阅读 · 0 评论 -
停止基于线程的服务(一)
停止基于线程的服务应用程序通常会创建拥有多个线程的服务,如 线程池 即可以表示一种拥有多个线程的服务。应用程序退出时,这些服务所拥有的线程也应该结束,JVM 才能被正常关闭。在 Java 中,线程由 Thread 对象表示,且和其它对象一样可以被自由共享。此外,线程有其所有者,即创建该线程的类,如线程池即是其工作者线程的所有者,应该通过线程的所有者来操控它们。和其它封装对象一样,线程的所有权是不可传递的:应用程序可以拥有服务,服务也可以拥有工作者线程,但应用程序不能拥有工作者线程,因此应用程序不能直接原创 2021-01-07 17:21:00 · 89 阅读 · 0 评论 -
阻塞方法
阻塞方法线程阻塞和阻塞方法被阻塞的线程往往需要等待一个不受它控制的事件发生后才能继续执行,如等待I/O操作完成,等待某个锁可用或等待一个外部计算结束。而可以导致线程阻塞的方法,我们称为 阻塞方法。在 Java 中,能抛出 InterruptedException 的方法一定是阻塞方法,这个异常会在处于阻塞状态的线程被中断时抛出。Java 中,每个线程有一个中断状态,Thread 提供了 interrupt 方法用以中断线程(设置中断状态)。需要注意的是,中断是一种协作机制。一个线程不能强制另一个线程原创 2020-12-13 15:00:04 · 1340 阅读 · 0 评论 -
基于不同任务执行策略的 Web 服务器
基于不同任务执行方式的 Web 服务器在任务执行策略一文中,简单介绍了 Java 常见的三种任务执行策略及其优缺点。本文将介绍分别基于这三种任务执行策略的服务器的特点,以说明在特定的场景中,合适的任务执行策略的重要性。单线程 Web 服务器该例程是一个串行的 Web 服务器,该服务器每次只能接受一个请求,主线程在接受连接和处理相关请求等操作间不断地交替运行,该策略使得服务器资源利用率低,无法提供高吞吐率或快速响应性。public class SingleThreadWebServer { p原创 2020-12-14 21:29:00 · 93 阅读 · 0 评论 -
管理延迟任务和周期任务以及获取任务的结果
延迟任务和周期任务在 Java 中,管理延迟和周期任务主要有两种方式:Timer 和 ScheduledThreadPoolExecutorTimerTimer 可以管理延迟任务和周z期任务,但存在一些缺陷:Timer 是单线程的,如果某个任务执行时间过长可能会破坏其它 TimerTask 的定时准确性。Timer 线程不会捕捉异常,若 TimerTask 抛出未受查异常则将终止整个 Timer 线程,该状况称为线程泄露(Thread Leakage)。Timer 只支持绝对时间而非相对时间原创 2020-12-14 21:06:11 · 166 阅读 · 0 评论 -
Executor
Executor在 Java 类库中,任务执行的主要抽象不是 Thread,而是 Executor。虽然 Executor 只是一个简单的接口,但却为 JDK 中灵活且强大的异步任务执行框架提供了基础。异步任务执行框架使用 Runnable 表示任务,能支持多种任务执行策略,且提供了一种标准方法将任务的提交和执行解耦。此外,Executor 的实现还提供了对生命周期的支持,以及统计信息收集、应用程序管理机制和性能监视等机制。Executor 基于生产者-消费者模式,提交任务的操作相当于生产者,执行任原创 2020-12-13 16:30:46 · 1463 阅读 · 0 评论 -
任务执行策略
执行执行策略执行任务的方式可以分为两类:串行执行和并行执行。其中,串行执行即执行完一个任务后再执行下一个,是单线程的;而并行执行的方式则有许多种,取决于你的并行策略。下面介绍 Java 常见的三种任务执行方式。串行执行每次只能执行一个任务,若服务器程序使用串行处理机制通常无法提供高吞吐量和快速响应性。为每个任务分配一个线程增加线程可以提高系统吞吐率,但问题是无限制的创建线程非但降低性能,而且可能会引发危险。使用ExecutorExecutor 是 Java 类库中的一个接口,提供了标准方法将任原创 2020-12-13 15:56:32 · 881 阅读 · 0 评论 -
同步容器存在的并发问题
同步容器java.util 中,存在一些古老的同步容器类,如 Vector、Hashtable。这些同步容器类,主要依靠持有内部锁(synchronized 修饰方法)来保证对容器状态访问的原子性。因此,几乎所有需要访问容器状态的方法,都是 synchronized 修饰的同步方法。虽然保证了线程安全,但也极大降低了并发性,使得同步容器在并发场景下堪忧的性能令人诟病。并发问题如果单独使用同步容器所提供的操作,可以放心使用,不会带来任何的并发问题。因为同步逻辑已经被封装在该操作对应的方法中。但如果使用复原创 2020-10-01 17:35:29 · 168 阅读 · 0 评论