Balking模式
线程任务发现其他线程正在执行相同的工作而放弃即将开始的任务。下面实例模拟word文档自动保持和手动保持功能来了解。当手动保持和自动保持冲突时,自动保持放弃执行其任务。
文档类
/**
* 文档类
*/
public class Document {
// 是否被修改标识
private boolean changed = false;
// 要保存的内容
private List<String> content = new ArrayList<>();
// 输出流
private final FileWriter writer;
// 自动保持文件的线程
private static AutoSaveThread autoSaveThread;
// 构造传入文件的路径和名称
private Document(String path,String name) throws IOException {
this.writer = new FileWriter(new File(path,name),true);
}
// 静态方法 用于创建文档 并开启自动保持文档的线程
public static Document create(String path,String name) throws IOException{
Document document = new Document(path, name);
autoSaveThread = new AutoSaveThread(document);
autoSaveThread.start();
return document;
}
// 文档编写, 将编写信息设置到content中
public void edit(String content){
synchronized (this){
this.content.add(content);
this.changed = true;
}
}
// 文档关闭 先中断自动保持线程 再关闭writer释放资源
public void close() throws IOException{
autoSaveThread.interrupt();
writer.close();
}
// 保存
public void save() throws IOException{
synchronized (this){
// balking 如果文档已经保存 则直接返回
if (!changed){
return;
}
System.out.println("线程为"+Thread.currentThread().getName()+"------------开始调用保存-----------");
for (String caheLine:content){
this.writer.write(caheLine);
this.writer.write("\r\n");
}
this.writer.flush();
// 修改标识 清空修改内容
this.changed = false;
this.content.clear();
}
}
}
自动保存文档线程类
/**
* 自动保存线程
*/
public class AutoSaveThread extends Thread {
private final Document document;
public AutoSaveThread(Document document) {
// 设置线程别名
super("自动保存线程");
this.document = document;
}
@Override
public void run() {
while (true){
try {
// 每隔一秒保存一次文档
document.save();
TimeUnit.SECONDS.sleep(1);
}catch (IOException | InterruptedException e){
break;
}
}
}
}
文档使用线程类
/**
* 该线程 类似于主动编辑文档的作者 使用文档
*/
public class DocumentEditThread extends Thread{
// 文件地址
private final String path;
// 文件名称
private final String name;
// 命令行输入
private final Scanner scanner = new Scanner(System.in);
public DocumentEditThread(String path, String name) {
super("文档编写线程");
this.path = path;
this.name = name;
}
@Override
public void run() {
int time = 0;
try {
Document document = Document.create(path, name);
while (true){
// 获取用户键盘输入
String next = scanner.next();
// 退出
if("quit".equals(next)){
document.close();
break;
}
// 编辑
document.edit(next);
// 模拟手动保存
if (time == 5){
document.save();
time = 0;
}
time++;
}
}catch (IOException e){
throw new RuntimeException(e);
}
}
}
测试类
public class BalkingTest {
public static void main(String[] args) {
new DocumentEditThread("C:\\Java","balking.txt").start();
}
}
当第六次输入信息保存时会走手动保存
1111
线程为自动保存线程------------开始调用保存-----------
2222
线程为自动保存线程------------开始调用保存-----------
3333
线程为自动保存线程------------开始调用保存-----------
4444
线程为自动保存线程------------开始调用保存-----------
5555
线程为自动保存线程------------开始调用保存-----------
6666
线程为文档编写线程------------开始调用保存-----------
quit
使用balking模式实现资源只被加载一次
private boolean loaded = false;
private final Map<String,List<String>> applicationContext = new HashMap<>();
public synchronized Map<String, List<String>> load(){
//balking 标识为true时取已经加载好的数据
if(loaded){
return applicationContext;
}else {
// 初始化一次
applicationContext = new HashMap<>();
this.loaded = true;
return applicationContext;
}
}