《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,如需转载请自行联系原作者
相关文章
|
3天前
|
人工智能 缓存 监控
使用LangChain4j构建Java AI智能体:让大模型学会使用工具
AI智能体是大模型技术的重要演进方向,它使模型能够主动使用工具、与环境交互,以完成复杂任务。本文详细介绍如何在Java应用中,借助LangChain4j框架构建一个具备工具使用能力的AI智能体。我们将创建一个能够进行数学计算和实时信息查询的智能体,涵盖工具定义、智能体组装、记忆管理以及Spring Boot集成等关键步骤,并展示如何通过简单的对话界面与智能体交互。
68 1
|
2月前
|
数据采集 搜索推荐 Java
Java 大视界 -- Java 大数据在智能教育虚拟学习环境构建与用户体验优化中的应用(221)
本文探讨 Java 大数据在智能教育虚拟学习环境中的应用,涵盖多源数据采集、个性化推荐、实时互动优化等核心技术,结合实际案例分析其在提升学习体验与教学质量中的成效,并展望未来发展方向与技术挑战。
|
4月前
|
自然语言处理 前端开发 Java
JBoltAI 框架完整实操案例 在 Java 生态中快速构建大模型应用全流程实战指南
本案例基于JBoltAI框架,展示如何快速构建Java生态中的大模型应用——智能客服系统。系统面向电商平台,具备自动回答常见问题、意图识别、多轮对话理解及复杂问题转接人工等功能。采用Spring Boot+JBoltAI架构,集成向量数据库与大模型(如文心一言或通义千问)。内容涵盖需求分析、环境搭建、代码实现(知识库管理、核心服务、REST API)、前端界面开发及部署测试全流程,助你高效掌握大模型应用开发。
407 5
|
3月前
|
安全 算法 Java
Java 多线程:线程安全与同步控制的深度解析
本文介绍了 Java 多线程开发的关键技术,涵盖线程的创建与启动、线程安全问题及其解决方案,包括 synchronized 关键字、原子类和线程间通信机制。通过示例代码讲解了多线程编程中的常见问题与优化方法,帮助开发者提升程序性能与稳定性。
140 0
|
7天前
|
人工智能 Java API
Java与大模型集成实战:构建智能Java应用的新范式
随着大型语言模型(LLM)的API化,将其强大的自然语言处理能力集成到现有Java应用中已成为提升应用智能水平的关键路径。本文旨在为Java开发者提供一份实用的集成指南。我们将深入探讨如何使用Spring Boot 3框架,通过HTTP客户端与OpenAI GPT(或兼容API)进行高效、安全的交互。内容涵盖项目依赖配置、异步非阻塞的API调用、请求与响应的结构化处理、异常管理以及一些面向生产环境的最佳实践,并附带完整的代码示例,助您快速将AI能力融入Java生态。
114 12
|
6天前
|
人工智能 Java API
构建基于Java的AI智能体:使用LangChain4j与Spring AI实现RAG应用
当大模型需要处理私有、实时的数据时,检索增强生成(RAG)技术成为了核心解决方案。本文深入探讨如何在Java生态中构建具备RAG能力的AI智能体。我们将介绍新兴的Spring AI项目与成熟的LangChain4j框架,详细演示如何从零开始构建一个能够查询私有知识库的智能问答系统。内容涵盖文档加载与分块、向量数据库集成、语义检索以及与大模型的最终合成,并提供完整的代码实现,为Java开发者开启构建复杂AI智能体的大门。
216 1
|
13天前
|
安全 Java API
使用 Java 构建强大的 REST API 的四个基本技巧
本文结合探险领域案例,分享Java构建REST API的四大核心策略:统一资源命名、版本控制与自动化文档、安全防护及标准化异常处理,助力开发者打造易用、可维护、安全可靠的稳健API服务。
86 2
|
5月前
|
机器学习/深度学习 消息中间件 存储
【高薪程序员必看】万字长文拆解Java并发编程!(9-2):并发工具-线程池
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的强力并发工具-线程池,废话不多说让我们直接开始。
189 0
|
3月前
|
NoSQL Java 数据库
Java 全栈学习超全面知识图谱构建完整 Java 知识体系
本文全面讲解Java核心技术体系,涵盖基础语法、面向对象、集合框架、主流框架(Spring、Spring Boot、MyBatis)及三大实战项目(微服务电商、响应式博客、企业后台系统),助你系统掌握Java全栈开发技能。
222 1
|
3月前
|
Java Shell Maven
【Azure Container App】构建Java应用镜像时候遇无法编译错误:ERROR [build 10/10] RUN ./mvnw.cmd dependency:go-offline -B -Dproduction package
在部署Java应用到Azure Container App时,构建镜像过程中出现错误:“./mvnw.cmd: No such file or directory”。尽管项目根目录包含mvnw和mvnw.cmd文件,但依然报错。问题出现在Dockerfile构建阶段执行`./mvnw dependency:go-offline`命令时,系统提示找不到可执行文件。经过排查,确认是mvnw文件内容异常所致。最终通过重新生成mvnw文件解决该问题,镜像成功构建。

热门文章

最新文章