当前位置: 首页 > article >正文

第22章 Balking设计模式(Java高并发编程详解:多线程与系统设计)

1.什么是Balking设计

多个线程监控某个共享变量,A线程监控到共享变量发生变化后即将触发某个动作,但是此时发现有另外一个线程B 已经针对该变量的变化开始了行动,因此A便放弃了准备开始的工作, 我们把这样的线程间交互称为Balking(犹豫) 设计模式。其实这样的场景在生活中很常见,比如你去饭店吃饭,吃到途中想要再点一个小菜,于是你举起手示意服务员(见图22-1),其中一个服务员看到了你举手正准备走过来的时候,发现距离你比较近的服务员已经准备要受理你的请求于是中途放弃了。

2.Balking模式之文档编辑

2.1 Document

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

// 代表正在编辑的文档类
public class Document {
    // 如果文档发生改变,changed会被设置为true;
    private boolean changed = false;

    // 一次需要保存的内容,可以将其理解为内容缓存
    private List<String> content = new ArrayList<>();

    private final FileWriter writer;

    // 自动保存文档的线程
    private static AutoSaveThread autoSaveThread;

    // 构造函数需要传入文档保存的路径和文档名称
    private Document(String documentPath, String documentName) throws IOException {
        this.writer = new FileWriter(new File(documentPath, documentName));
    }

    // 静态方法,主要用于创建文档,顺便启动自动保存文档的线程
    private static Document create(String documentPath, String documentName) throws IOException {
        Document document = new Document(documentPath, documentName);
        autoSaveThread = new AutoSaveThread(document);
        autoSaveThread.start();
        return document;
    }

    // 文档编辑,其实就是往document队列中提交字符串
    public void edit(String content) {
        synchronized (this) {
            this.content.add(content);
            // 文档改变,changed会变为true
            this.changed = true;
        }
    }

    // 文档关闭的时候,首先中断自动保存线程,然后关闭writer释放资源
    public void close() throws IOException {
        autoSaveThread.interrupt();
        writer.close();
    }

    // save 方法用于为外部显示进行文档保存
    public void save() throws IOException {
        synchronized (this) {
            // balking, 如果文档已经保存了,则直接返回
            if ( !changed ) {
                return;
            }

            System.out.println(Thread.currentThread() + " execute the save action");
            for(String cacheLine: content) {
                this.writer.write(cacheLine);
                this.writer.write("\r\n");
            }
            this.writer.flush();
            this.changed = false;
            this.content.clear();
        }
    }

}

在上述代码中:

  • edit方法和save方法进行方法同步, 其目的在于防止当文档在保存的过程中如果遇到新的内容被编辑时引起的共享资源冲突问题。
  • changed在默认情况下为false, 当有新的内容被编辑的时候将被修改为true。
  • 在进行文档保存的时候, 首先查看changed是否为true, 如果文档发生过编辑则在文档中保存新的内容, 否则就会放弃此次保存动作, changed是balking pattern关注的状态, 当changed为true的时候就像远处的服务员看到客户的请求被另外一个服务员接管了一样,于是放弃了任务的执行。
  • 在创建Document的时候, 顺便还会启动自动保存文档的线程, 该线程的主要目的在于在固定时间里执行一次文档保存动作。

2.2 AutoSaveThread

import java.io.IOException;
import java.util.concurrent.TimeUnit;

public class AutoSaveThread extends Thread{
    private final Document document;

    public AutoSaveThread(Document document) {
        super("DocumentAutoSaveThread");
        this.document = document;
    }

    @Override
    public void run() {
        while(true) {
            try {
                document.save();
                TimeUnit.SECONDS.sleep(1);
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
    }
}

2.3 DocumentEditThread

AutoSave Thread线程用于文档自动保存, 那么DocumentEd it Thread线程则类似于主动编辑文档的作者, 在DocumentEd it Thread中除了对文档进行修改编辑之外, 还会同时按下Ctrl+S组合键(调用save方法) 主动保存, 见代码清单22-3。

import java.io.IOException;
import java.util.Scanner;

public class DocumentEditThread extends Thread{
    private final String documentPath;
    private final String documentName;

    private final Scanner scanner = new Scanner(System.in);

    DocumentEditThread(String documentPath, String documentName) {
        super("D");
        this.documentPath = documentPath;
        this.documentName = documentName;
    }

    @Override
    public void run() {
        int times = 0;

        try {
            Document document = Document.create(documentPath, documentName);

            while(true) {
                // 获取用户的键盘输入
                String text = scanner.next();
                if ( "quit".equals(text) ) {
                    document.close();
                    break;
                }
                // 将内容编辑到document中
                document.edit(text);
                if( times == 5) {
                    document.save();
                    times = 0;
                }
                times++;
            }

        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}

资源文件加载


http://www.kler.cn/a/541418.html

相关文章:

  • 荣耀手机Magic3系列、Magic4系列、Magic5系列、Magic6系列、Magic7系列详情对比以及最新二手价格预测
  • 项目的虚拟环境的搭建与pytorch依赖的下载
  • 【目标检测xml2txt】label从VOC格式xml文件转YOLO格式txt文件
  • 点大商城V2-2.6.6源码全开源uniapp +搭建教程
  • Java数据结构 | TreeMap 和 TreeSet
  • 如何使用Gemini模型,国内如何订阅购买Gemini Pro的教程,Gemini Pro 免费试用操作步骤, 谷歌 aistudio 使用入口
  • 牛客周赛Round 80 —— 举手赢棋 python 补题 + 题解
  • 数据结构之八大排序算法
  • Visual Studio 2022 中使用 Google Test
  • k8s:pod被kill,显示command terminated with exit code 137
  • Python Pandas(7):Pandas 数据清洗
  • UDP小实验
  • #渗透测试#批量漏洞挖掘#某成科信票务管理系统 TicketManager SQL注入漏洞
  • MapReduce简单应用(三)——高级WordCount
  • C#操作excel数据,第一步先保存到Redis,第二步再保存到Sql Server数据库。第三步同步到MongoDB中
  • Lisp语言的算法
  • 51单片机独立按键的扩展应用
  • Linux ping不通百度但浏览器可以打开百度的的解决方法
  • 抖音“碰一碰”发视频:短视频社交的新玩法
  • 【设计模式】【行为型模式】职责链模式(Chain of Responsibility)
  • 集成学习 网络安全 网络安全集成服务
  • HTML之JavaScript变量和数据类型
  • 【OneAPI】通过网页预渲染让搜索引擎收录网页
  • 如何通过 bugreport 分析 Android 系统日志?
  • flutter-webrtc安装示例
  • 简易图书管理系统——MYsql+Javase+JDBC