《Java并发编程实战》第十四章 构建自己定义的同步工具 读书笔记

简介:

一、状态依赖性的管理

有界缓存实现的基类
@ ThreadSafe
public abstract class BaseBoundedBuffer<E> {
       @GuardeBy( "this" ) private final E[] buf;
       @GuardeBy( "this" ) private int tail;
       @GuardeBy( "this" ) private int head;
       @GuardeBy( "this" ) private int count;

       protected BaseBoundedBuffer( int capacity) {
             this .buf = (E[]) new Object[capacity];
      }

       protected synchronized final void doPut(E E) {
            buf[tail] = E;
             if (++tail == buf.length) {
                  tail = 0;
            }
            ++count;
      }

       protected synchronized final E doTake() {
            E E = buf[head];
            buf[head] = null ;
             if (++head == buf.length) {
                  head = 0;
            }
            --count;
             return E;
      }

       public synchronized final boolean isFull() {
             return count == buf.length;
      }

       public synchronized final boolean isEmpty() {
             return count == 0;
      }
}


1 演示样例:将前提条件的失败传递给调用者
@ ThreadSafe
public class GrumpyBoundedBuffer<V> extends BaseBoundedBuffer<V> {
       public GrumpyBoundedBuffer( int size){
             super (size);
      }
      
       public synchronized void put(V v){
             if (isFull()){
                   throw new BufferFullException ();
            }
            doPut(v);
      }
      
       public synchronized V take(){
             if (isEmpty())
                   throw new BufferEmptyExeption ();
             return doTake();
      }
}

缓存为空或者已满都不是异常情况,使用者必需要捕获这些异常才干进行正确的处理。
       while (true ){
             try {
                  V item = buffer.take();
                   // 对于item运行一些操作
                   break ;
            } catch (BufferEmptyException e) {
                  Thread. sleep(SLEEP_GRANULARITY );
            }
      }


2 演示样例:通过轮询与休眠来实现简单的堵塞
从上面的代码能够看出。堵塞与出现异常都须要方法的使用者来处理,如今尝试都封装到有界缓存中。

@ ThreadSafe
public class SleepyBoundedBuffer<V> extends BaseBoundedBuffer<V> {
       public SleepyBoundedBuffer( int size) {
             super (size);
      }

       public void put(V v) throws InterruptedException{
             while (true ){
                   synchronized (this ){
                         if (!isFull()){
                              doPut(v);
                               return ;
                        }
                  }
                  Thread.sleep(SLEEP_GRANULARITY);
            }
      }
      
       public V take() throws InterruptedException{
             while (true ){
                   synchronized (this ){
                         if (!isEmpty()){
                               return doTake();
                        }
                  }
                  Thread.sleep(SLEEP_GRANULARITY);
            }
      }
}

3 条件队列
不须要使用while(true),改为使用wait、notifyAll
@ ThreadSafe
public class BoundedBuffer<V> extends BaseBoundedBuffer<V> {

       // 条件谓词:not-full (!isFull())
       // 条件谓词:not-empty (!isEmpty())
      
       public BoundedBuffer( int size) {
             super (size);
      }
      
       // 堵塞并直道:not-full
       public synchronized void put(V v) throws InterruptedException{
             while (isFull()){
                  wait();
            }
            doPut(v);
            notifyAll();
      }
      
       // 堵塞并直道:not-empty
       public synchronized V take() throws InterruptedException{
             while (isEmpty()){
                  wait();
            }
            V v = doTake();
            notifyAll();
             return v;
      }
}

二、使用条件队列

1 条件谓词
要想正确地使用条件队列,关键是找出对象在哪个条件谓词上等待。

2 过早唤醒
比如:内置条件队列中有多个条件谓语。此时假设调用notifyAll其含义是通知全部wait,可是并不一定全部条件谓语都满足运行条件。


当使用条件等待时(比如Object.wait或Condition.await):
. 通常都有一个条件谓词--包含一些对象状态的測试,线程在运行前必须首先通过这些測试。


. 在调用wait之前測试条件谓词,而且从wait中返回时再次进行測试。
. 在一个循环中调用wait。
. 确保使用与条件队列相关的锁来保护构成条件谓词的各个状态变量。
. 当调用wait、notify或notifyAll等方法时。一定要持有与条件队列相关的锁。
. 在检查条件谓词之后以及開始运行对应的操作之前。不要释放锁。


3 丢失的信号
已经满足通知的条件发出通知,可是之后才进入堵塞wait状态。所以wait永远等不到在其前面发出的notify。

4 通知
5 演示样例:阀门类
6 子类的安全问题
7 封装条件队列
8 入口协议与出口协议


三、显式的Condition对象
四、Synchronizer剖析
五、AbstractQueuedSynchronizer
六、java.util.concurrent同步器类中的 AQS
1 ReentrantLock
2 Semaphore与CountDownLatch
3 FutureTask
4 ReentrantReadWriteLock







本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5171998.html,如需转载请自行联系原作者
相关文章
|
8天前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
13天前
|
安全 Java 开发者
告别NullPointerException:Java Optional实战指南
告别NullPointerException:Java Optional实战指南
185 119
|
15天前
|
人工智能 算法 Java
Java与AI驱动区块链:构建智能合约与去中心化AI应用
区块链技术和人工智能的融合正在开创去中心化智能应用的新纪元。本文深入探讨如何使用Java构建AI驱动的区块链应用,涵盖智能合约开发、去中心化AI模型训练与推理、数据隐私保护以及通证经济激励等核心主题。我们将完整展示从区块链基础集成、智能合约编写、AI模型上链到去中心化应用(DApp)开发的全流程,为构建下一代可信、透明的智能去中心化系统提供完整技术方案。
135 3
|
16天前
|
机器学习/深度学习 人工智能 监控
Java与AI模型部署:构建企业级模型服务与生命周期管理平台
随着企业AI模型数量的快速增长,模型部署与生命周期管理成为确保AI应用稳定运行的关键。本文深入探讨如何使用Java生态构建一个企业级的模型服务平台,实现模型的版本控制、A/B测试、灰度发布、监控与回滚。通过集成Spring Boot、Kubernetes、MLflow和监控工具,我们将展示如何构建一个高可用、可扩展的模型服务架构,为大规模AI应用提供坚实的运维基础。
129 0
|
17天前
|
人工智能 Java 物联网
Java与边缘AI:构建离线智能的物联网与移动应用
随着边缘计算和终端设备算力的飞速发展,AI推理正从云端向边缘端迁移。本文深入探讨如何在资源受限的边缘设备上使用Java构建离线智能应用,涵盖从模型优化、推理加速到资源管理的全流程。我们将完整展示在Android设备、嵌入式系统和IoT网关中部署轻量级AI模型的技术方案,为构建真正实时、隐私安全的边缘智能应用提供完整实践指南。
182 3
|
18天前
|
人工智能 监控 Java
Java与AI智能体:构建自主决策与工具调用的智能系统
随着AI智能体技术的快速发展,构建能够自主理解任务、制定计划并执行复杂操作的智能系统已成为新的技术前沿。本文深入探讨如何在Java生态中构建具备工具调用、记忆管理和自主决策能力的AI智能体系统。我们将完整展示从智能体架构设计、工具生态系统、记忆机制到多智能体协作的全流程,为Java开发者提供构建下一代自主智能系统的完整技术方案。
197 4
|
19天前
|
机器学习/深度学习 分布式计算 Java
Java与图神经网络:构建企业级知识图谱与智能推理系统
图神经网络(GNN)作为处理非欧几里得数据的前沿技术,正成为企业知识管理和智能推理的核心引擎。本文深入探讨如何在Java生态中构建基于GNN的知识图谱系统,涵盖从图数据建模、GNN模型集成、分布式图计算到实时推理的全流程。通过具体的代码实现和架构设计,展示如何将先进的图神经网络技术融入传统Java企业应用,为构建下一代智能决策系统提供完整解决方案。
191 0
|
23天前
|
人工智能 缓存 自然语言处理
Java与多模态AI:构建支持文本、图像和音频的智能应用
随着大模型从单一文本处理向多模态能力演进,现代AI应用需要同时处理文本、图像、音频等多种信息形式。本文深入探讨如何在Java生态中构建支持多模态AI能力的智能应用。我们将完整展示集成视觉模型、语音模型和语言模型的实践方案,涵盖从文件预处理、多模态推理到结果融合的全流程,为Java开发者打开通往下一代多模态AI应用的大门。
201 41
|
25天前
|
人工智能 Java API
Java AI智能体实战:使用LangChain4j构建能使用工具的AI助手
随着AI技术的发展,AI智能体(Agent)能够通过使用工具来执行复杂任务,从而大幅扩展其能力边界。本文介绍如何在Java中使用LangChain4j框架构建一个能够使用外部工具的AI智能体。我们将通过一个具体示例——一个能获取天气信息和执行数学计算的AI助手,详细讲解如何定义工具、创建智能体并处理执行流程。本文包含完整的代码示例和架构说明,帮助Java开发者快速上手AI智能体的开发。
607 8
|
26天前
|
人工智能 缓存 监控
使用LangChain4j构建Java AI智能体:让大模型学会使用工具
AI智能体是大模型技术的重要演进方向,它使模型能够主动使用工具、与环境交互,以完成复杂任务。本文详细介绍如何在Java应用中,借助LangChain4j框架构建一个具备工具使用能力的AI智能体。我们将创建一个能够进行数学计算和实时信息查询的智能体,涵盖工具定义、智能体组装、记忆管理以及Spring Boot集成等关键步骤,并展示如何通过简单的对话界面与智能体交互。
557 1