一,什么是Balking模式

如果现在不合适执行这个操作,或者没必要执行这个操作,就停止处理,直接返回。
在Balking模式中,如果守护条件不成立,就立即中断处理。

二,例子:

定期将当前数据内容写入文件中,比如文本工具的自动保存功能,定期的将数据保存到文件中。
当数据内容被写入时,会完全覆盖上次写入的内容,只有最新的内容才会被保存
当写入的内容和上次的内容完全相同时,再向文件写入就多余了,所以就不再执行写入操作。
所以这个程序就是以 数据内容不同 作为守护条件,如果数据内容相同,就不执行写入操作,直接返回(balk)

代码:

Data类:可以修改并保存的数据的类

ChangerThread类:模仿用户,进行文本的修改并随时保存

SaverThread类:执行自动保存的线程

public class Data {

    private final String filename;
private String content;
private boolean changed; public Data(String filename, String content) {
this.filename = filename;
this.content = content;
this.changed = true;
}
//修改了数据内容
public synchronized void change(String newContent){
content = newContent;
changed = true;
}
//若数据修改过,则保存到文件中
public synchronized void save() throws IOException{
if (!changed){
//如果没有修改,就不保存了
return;
}
doSave();
changed = false;
}
//将数据内容保存到文件中
public void doSave() throws IOException{
System.out.println(Thread.currentThread().getName()+" calls doSave, content ="+content);
Writer writer = new FileWriter(filename);
writer.write(content);
writer.close();
}
}
public class ChangerThread extends Thread{

    private final Data data;
private final Random random = new Random(); public ChangerThread(String name,Data data) {
super(name);
this.data = data;
} @Override
public void run() {
try {
for (int i = 0; true; i++) {
data.change("NO."+i);//修改数据
Thread.sleep(random.nextInt(1000));//执行其他操作
data.save();//显示的保存,用户自己点击保存
}
}catch (IOException e){
e.printStackTrace();
}catch (InterruptedException e){
e.printStackTrace();
} }
}
public class SaverThread extends Thread{
private final Data data; public SaverThread(String name,Data data) {
super(name);
this.data = data;
} @Override
public void run() {
try {
while (true){
data.save();//要求保存数据
Thread.sleep(1000);//休眠约一秒
}
}catch (IOException e){
e.printStackTrace();
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
public class Test {
public static void main(String[] args) {
Data data = new Data("data.txt","(empty)");
new ChangerThread("ChangeThread",data).start();
new SaverThread("SaverThread",data).start(); }
}

三,GurardedObject:被防护的对象

GuardedObject角色是一个拥有被防护的方法的类。当线程执行guardedMethod时,若守护条件成立,则执行实际的处理。
当守护条件不成立时,不执行实际的处理,直接返回。守护条件是否成立,会随着GuardedObject角色的状态变化而变化
Data类就是被防护的对象
save方法对应guardedMethod
change方法对应stateChangingMethod

四,何时使用Balking模式

1.并不需要执行时:
比如上面的程序中,文件已经手动保存了,并且文本内容也没有改变,就不需要再执行自动保存了。这样可以提高程序性能
2.不需要等待守护条件成立时
当守护条件不成立时,就立即返回并进入下一个操作,就可以使用这种模式。这能够提高程序的响应性
3.守护条件仅在一次成立时
相当于没有stateChangingMethod方法的情况
例子:

public class Something{
private boolean initialized = false;
public synchronized void init(){
if(initialized){
return;
}
doInit();
initialized = true; } public void doInit(){
//实际处理初始化
}
} //如果没有初始化,就做一次初始化动作。如果已经初始化就什么也不做。直接返回

五,balk结果的表示方式

1.忽略balk
不通知调用端发生了balk,比如实例程序中直接return
2.通过返回值来表示balk
比如返回值为true,表明为发生balk。如果返回值为false,说明发生了balk,处理并未被执行
3.通过异常来表示balk的发生
当balk发生时,程序并不是从方法中retrun,而是直接抛出异常

六,超时

Balking模式中,当守护条件不成立时,线程会直接balk并返回
而Guarded Suspension模式中,当守护条件不成立时,线程会一直等待到成立为止。
这两种模式都比较极端。还有一种处理方方法,在守护条件成立之前等待一段时间,如果到时条件还未成立,则直接balk。这种处理称为 guarded timed或timeout

1.wait何时终止?
当执行: obj.wait();时,线程进入obj的等待队列,停止运行,并释放持有的obj锁。当下面情况发生时,线程就会退出等待线程:
notify方法执行
notifyAll方法执行
interrupt方法执行
超时发生时

2.guarded timed的实现
从上面的方法得知,我们无法区分wait方法是被notify/notifyAll了,还是超时了,所以自己要实现guarded timed。判断wait是否超时
代码:

public class Host {

    private final long timeout;//超时时间
private boolean ready = false;//方法正常执行时为true public Host(long timeout){
this.timeout = timeout;
} //修改状态
public synchronized void setExecutable(boolean on){
ready =on;
notifyAll();
}
//检查状态后在执行
public synchronized void execute()throws InterruptedException,TimeoutException{
long start = System.currentTimeMillis();//开始时间
while (!ready){
long now = System.currentTimeMillis();//当前时间
long rest = timeout - (now -start);
       //在这里只要 <=0,我们就认为超时。(因为wait方法的参数为0时,就表示没有超时时间(超时时间无限长),当传入负数时,会抛出IllegalArgumentException异常。)
if (rest <= 0){
throw new TimeoutException("now - start= "+(now-start)+", timeout = "+timeout);
}
wait(rest);
}
     doExecute();
}
//实际的处理
private void doExecute(){
System.out.println(Thread.currentThread().getName()+" calls doExecute");
} }
/*
如果Host的方法执行时,不调用setExecutable(true),程序就会出现超时
*/
public class Test { public static void main(String[] args) {
Host host = new Host(10000);
try {
System.out.println("execute Begin");
host.execute();
}catch (TimeoutException e){
e.printStackTrace();
}catch (InterruptedException e){
e.printStackTrace();
}
}
}

执行结果:

execute Begin
java.util.concurrent.TimeoutException: now - start= 10001, timeout = 10000  //误差1毫秒
    at com.amazing.jdk.myThread.package12.Host.execute(Host.java:29)
    at com.amazing.jdk.myThread.package12.Test.main(Test.java:14)

多线程系列之五:Balking 模式的更多相关文章

  1. 多线程学习之五超时模式Timer

    timed[超时模式]案例:一个线程提供下载数据,另一个线程执行下载,如果有5秒钟以上,提供下载的线程没有提供数据,下载线程因超时异常,停止下载线程运行. 超时异常类 /** * */ package ...

  2. Android多线程分析之五:使用AsyncTask异步下载图像

    Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<An ...

  3. java多线程系列(三)---等待通知机制

    等待通知机制 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理解 ...

  4. java多线程系列 目录

    Java多线程系列1 线程创建以及状态切换    Java多线程系列2 线程常见方法介绍    Java多线程系列3 synchronized 关键词    Java多线程系列4 线程交互(wait和 ...

  5. Java多线程系列——原子类的实现(CAS算法)

    1.什么是CAS? CAS:Compare and Swap,即比较再交换. jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronou ...

  6. Java多线程系列——从菜鸟到入门

    持续更新系列. 参考自Java多线程系列目录(共43篇).<Java并发编程实战>.<实战Java高并发程序设计>.<Java并发编程的艺术>. 基础 Java多线 ...

  7. OpenvSwitch系列之五 网桥特性功能配置

    Open vSwitch系列之一 Open vSwitch诞生 Open vSwitch系列之二 安装指定版本ovs Open vSwitch系列之三 ovs-vsctl命令使用 Open vSwit ...

  8. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  9. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

随机推荐

  1. win8系统电脑自动关机怎么取消

    在使用win8系统的用户会遇到电脑自动关机的情况,这是win8自带的自动关机功能,如果想取消这个功能,只需要通过执行一个命令即可实现.下面小编来为大家讲解一下具体步骤. 1.组合键:win+R,然后在 ...

  2. python3编写网络爬虫18-代理池的维护

    一.代理池的维护 上面我们利用代理可以解决目标网站封IP的问题 在网上有大量公开的免费代理 或者我们也可以购买付费的代理IP但是无论是免费的还是付费的,都不能保证都是可用的 因为可能此IP被其他人使用 ...

  3. sboot mybatis

    https://www.cnblogs.com/lspz/p/6723603.html spring.datasource.url=jdbc:mysql://10.46.52.205:3306/tes ...

  4. 设计模式のAbstractFactory(虚拟工厂)----创建模式

    一.产生背景 抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂.该超级工厂又称为其他工厂的工厂.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最 ...

  5. idea在maven打包时运行Test测试, 导致打包失败, 乱七八糟的错误

    在maven打包时运行Test测试, 导致打包失败, 乱七八糟的错误 在maven projects中图标toggle'skip Tests' Mode //宏杰帮助 网上案例:https://blo ...

  6. UVA10817-Headmaster's Headache(动态规划基础)

    Problem UVA10817-Headmaster's Headache Time Limit: 4500 mSec Problem Description Input The input con ...

  7. 第11章 AOF持久化

    AOF持久化在硬盘上保存的是对Redis进行的逻辑操作,类似InnoDB中的bin log.说白了就是你对一个Redis输入了哪些语句,AOF文件都会原封不动的保存起来,等到需要回复Redis的时候再 ...

  8. HashMap 1.7

    1.关键属性与内部类 1.1属性 使用拉链法解决hash冲突的hash表,hash表里存了多少个元素.数组有多长以及当什么情况下需要扩容是重要的参数. transient Entry<K,V&g ...

  9. (五)JavaScript 变量

    JavaScript 变量 与代数一样,JavaScript 变量可用于存放值(比如 x=5)和表达式(比如 z=x+y). 变量可以使用短名称(比如 x 和 y),也可以使用描述性更好的名称(比如 ...

  10. 吴恩达课后作业学习2-week3-tensorflow learning-1-基本概念

    参考:https://blog.csdn.net/u013733326/article/details/79971488 希望大家直接到上面的网址去查看代码,下面是本人的笔记  到目前为止,我们一直在 ...