Java知识分享
热爱技术,分享技术

并发编程实战:Balking设计模式

1. 什么是Balking设计

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

并发编程实战:Balking设计模式插图

2. Balking模式值文档编辑

2.1 Document

在下面代码中document代表文档本身,在Document中主要有两个方法save和edit分别用于保存文档和编辑文档。

package com.ibfbc.concurrency.balking;

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

import static java.lang.Thread.currentThread;

/**
 * 文档对象
 * Created by www.ibfbc.com
 */
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));
    }

    //创建文档,随便启动自动保存文档的线程
    public static Document create(String documentPath, String documentName) throws IOException {
        Document document = new Document(documentPath, documentName);
        autoSaveThread = new AutoSaveThread(document);
        autoSaveThread.start();
        return document;
    }

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

    //文档的编辑,其实就是向content队列中提交字符串
    public void close() throws IOException {
        autoSaveThread.interrupt();
        writer.close();
    }

    //外部显示调用存储
    public void save() throws IOException {
        synchronized (this) {
            //balking,如果文档已经被保存了则之间返回
            if (!changed) {
                return;
            }
        }
        System.out.println(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();
    }
}

在上述代码中:

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

2.2 AotuSaveThread

与平日里编写word文档一样,word会定期自动保存我们编辑的文档,如果在电脑出现故障重启之时,没有来得及对文档保存,也不至于损失太多劳动成果,它甚至能够百分之百的恢复,AutoSaveThread 类扮演的角色便在于此。

package com.ibfbc.concurrency.balking;

import java.util.concurrent.TimeUnit;

public class AutoSaveThread extends Thread {
private final Document document;

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

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

AutoSaveThread比较简单,其主要的工作就是每隔一秒的时间调用–document的save方法。

2.3 DocumentEditThread

AutoSaveThread线程用于文档自动保存,那么DocumentEditThread线程则类似于主动编辑文档的作者,在DocumentEditThread中除了对文档进行修改编辑之外,还会同时按下Ctrl+S组合键(调用save方法)主动保存。

package com.ibfbc.concurrency.balking;

import java.io.IOException;
import java.util.Scanner;
/**
* 文档编辑线程
* Created by www.ibfbc.com
*/
public class DocumentEditThread extends Thread {
private final String documentPath;
private final String documentName;
private final Scanner scanner = new Scanner(System.in);

public DocumentEditThread(String documentPath, String documentName) {
super("documentEditThread");
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.edit(text);
if (times == 5) {
document.save();
times = 0;
}
times++;
}
} catch (IOException e) {
e.printStackTrace();
}

}
}

DocumentEditThread类代表了主动编辑文档的线程,在该线程中,我们使用Scanner交互的方式,每一次对文档的修改都不可能直接保存( Ctrl+S),因此在程序中约定了五次以后主动执行保存动作,当输人quit时,表示要退出此次文档编辑,代码如下:

package com.ibfbc.concurrency.balking;
public class BalkingTest {
    public static void main(String[] args) {
        new DocumentEditThread("C:\\Users\\Administrator\\Desktop", "balking.txt").start();
    }
}
并发编程实战:Balking设计模式插图(1)
打赏
本站所有资源均来源于网络,仅供学习使用,请支持正版!Java技术开源 » 并发编程实战:Balking设计模式

评论 抢沙发

评论前必须登录!

 

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫

登录

找回密码

注册