【Backing模式】
如果现在不适合执行这个操作,或者没必要执行这个操作,就停止处理,直接返回。Balking模式与Guarded Suspension模式一样,也存在守护条件。在Balking模式中,如果守护条件不成立,则立即中断处理。这与Guarded Suspension模式有所不同,因为 Guarded Suspension模式是一直等待至可以运行。
【示例程序】
文本工具的自动保存功能,为了防止电脑突然死机而定期地将数据保存到文件的功能。
当写入的内容与上次写入的内容完全相同时,再向文件写入就显得多余了,所以就不再执行写入操作。也就是说,改程序以“数据内容存在不同”作为守护条件,如果数据内容相同,则不执行写入操作,直接返回balk。
名字 |
说明 |
Data |
表示可以修改并保存的数据的类 |
SaverThread |
定期保存数据内容的类 |
ChangerThread |
修改并保存数据内容的类 |
Main |
测试程序行为的类 |
public class Data {
private final String filename; //保存的文件名称
private String content; //数据内容
private boolean changed; //修改后的内容若未保存,则为true
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 SaverThread extends Thread {
private final Data data;
public SaverThread(String name, Data data) {
super(name);
this.data=data;
}
public void run() {
try{
while(true){
data.save();//要求保存数据
Thread.sleep(1000);//休眠约1秒
}
} catch(IOException e) {
e.printStackTrace();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
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;
}
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 static void main(String[] args) {
Data data = new Data("Data.txt", "(empty)");
new ChangerThread("ChangerThread",data).start();
new SaverThread("SaverThread",data).start();
}
【Balking模式登场的角色】
GuardObject被防护的对象
GuardObject角色是一个拥有被守护方法的类。当线程执行guardMethod方法时,若守护方法成立,则执行实际的处理。而当守护条件不成立时,则不执行实际的处理,直接返回。守护条件的成立与否,会随着GuardObject角色的状态变化而发生变化。
除了guardMethod之外,GuardObject角色还有可能有其他来改变状态的方法。
守护条件为changed字段为true.
【何时可用】
1.并不需要执行时
在示例程序中,content字段的内容并没有发生修改时,就将save方法balk了。
之所以balk,是因为content的内容已经写进文件中了,无需再耗费功夫去写了。
2.不需要等待守护条件成立时
Balking模式的特点就是“不进行等待”。若守护条件不成立时,想要立即返回并进入下一个操作。这能够提高程序的响应性。
3.守护条件仅在第一次成立时
【小结】
Balking模式——对象本身拥有状态,该对象只有在自身状态合适时才会执行处理,否则便不会执行处理。
使用if来检查守护条件
【练习题1】
阅读下面关于示例程序的内容,叙述正确请打√,错误请打×
1.save方法仅可由SaverThread调用
×答:save方法可由SaverThread和ChangerThread调用。
2.将所有的synchronized都删掉,并将changed字段声明为volatile之后,程序运行仍然是一样的。
×答:由于change方法㛑save方法都不再是Single Threaded Execution模式,运行也就不同。即使声明为volatile,线程的互斥处理也不会被执行。
3.doSave方法不是synchronized方法。
√答:doSave方法并不是synchronized方法。但是由于 doSave方法仅由synchronized方法调用,所以执行到doSave方法的线程一定持有this的锁。