读书人

Book01-No.4 判定间断模式

发布时间: 2012-08-22 09:50:35 作者: rapoo

Book01-No.4 判定中断模式

1、理解

Balking Pattern重在“balking”,balking的意思是“退缩不前”,在棒球运动的意思是“当跑垒员在垒时,投手在投手板但’中途放弃‘投球的动作”(呵呵,对棒球不懂...)。另外,这种模式和Guarded Suspension Pattern有点类似,也是有要检测警戒条件是否成立,不过,如果不成立,就不用等待了,直接就放弃了。呵呵,这种模式还是想的比较开啊(不行?那爷不赔你玩了:)),相比之下,Guarded Suspension Pattern就执着的多了:)。 从代码的角度看,如下: class A{ public synchronized void guardedMethod(){ if(警戒条件不成立){ return; } 进行处理 改变状态 } } 下面给出参考书中列出的一个使用Balking Pattern的实例:即文本编辑器的自动保存功能。当在编辑文件的时候,后台有个线程会定期的对文件进行保存,防止程序崩溃时文件内容的丢失。那么,文件是否被修改就是这里的警戒条件。当然,还得有另外一个字段,就是当前的数据。编辑程序会调用synchronized的方法对文件数据进行修改,并设置警戒条件(为什么用synchronized?是因为防止更改操作和保存的冲突,否则,可能保存的不是最新的数据)。那么,后台的定时保存线程,会定时调用保存文件这个guardedMethod(),如果文件已经被(编辑程序)保存了,那么就balking了,否则,就保存。

?

2、设计实现

?

创建一个小程序,但数据区发现有改动的时候,就写入到日志里面

?

package com.metarnet.BalkingPattern;import java.io.BufferedWriter;import java.io.File;import java.io.FileWriter;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Date;/** * 数据类,保存着当前的数据,有处理数据和保持数据的方法 * @author Administrator * */public class Data {private final String filename;private String content;private boolean isChanged = false;public static final String PATH = "D:" + File.separator + "info.log";public Data(String content, String filename, boolean isChanged) {super();this.content = content;this.filename = filename;this.isChanged = isChanged;}public synchronized void changedData(String content) {this.content = content;isChanged = true;}public synchronized void save() throws IOException {if(!isChanged) {return;}doSaved();isChanged = false;}private void doSaved() throws IOException {System.out.println(Thread.currentThread().getName() + " get changed data, so should be saved the data!");FileWriter fw = null;BufferedWriter bw = null;try {fw = new FileWriter(PATH, true);bw = new BufferedWriter(fw);bw.write(Thread.currentThread().getName() + " : " + content);System.out.println(Thread.currentThread().getName() + " : " + content);bw.newLine();bw.write("----" + new SimpleDateFormat("yyyy-MM-dd hh24:mm:ss").format(new Date()) + "----");bw.newLine();bw.newLine();bw.flush();} finally {if(bw != null) {bw.close(); bw = null;}if(fw != null) {fw.close();fw = null;}}}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public boolean isChanged() {return isChanged;}public void setChanged(boolean isChanged) {this.isChanged = isChanged;}public String getFilename() {return filename;}}
package com.metarnet.BalkingPattern;import java.io.IOException;/** *  * @author shma1664 2012年4月27日 14:55:40 * 保存数据的类,每隔一秒去扫描是否数据有更新,若有更新则写入日志中 * */public class SaveThread extends Thread {private Data data;public SaveThread(Data data, String name) {super(name);this.data = data;}@Overridepublic void run() {try {while(true) {data.save();Thread.sleep(1000);}} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}}}
package com.metarnet.BalkingPattern;import java.io.IOException;/** * 该类实现两个功能,一者是不断的更新数据,以便入日志,自己本身也有入日志的功能,在更新完数据的时候等待一段时间 * 也去保持。但是其和保持数据类一样,都有条件控制,当数据发送一次改变的时候,他们两个中只有一个会去改变,另外一个 * 当判断isChanged为false则返回了 * @author shma1664 2012年4月27日 14:59:23 * */public class ChangedDataThread extends Thread {private Data data;public ChangedDataThread(Data data, String name) {super(name);this.data = data;}@Overridepublic void run() {try {for(int i=0; true; ++i) {data.changedData("No." + i);Thread.sleep(800);data.save();}} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
package com.metarnet.BalkingPattern;public class TestDataMain {public static void main(String[] args) {Data data = new Data("no content", "data", true);SaveThread saveThread = new SaveThread(data, "Save-Thread");ChangedDataThread change = new ChangedDataThread(data, "changeData-Thread");saveThread.start();change.start();try {Thread.sleep(30000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}saveThread.interrupt();change.interrupt();}}
?

3、Balking Pattern何时使用:

?

不需要刻意执行的时候,当数据区未发生改变的时候,则不需要去处理,则可以直接退出。有改变则处理不想等待警戒条件成立时直接退出,而在上一个回合里面讲述的生产者消费者模式中则当警戒条件不成立的时候会一直等待到条件成立的时候再去执行。警戒条件只有第一个成立的时候,某些时候只需要执行一次,如初始化操作时,则可以使用,经常出现在实例初始化以及终结处理方面 , 如下设计:
package com.metarnet.BalkingPattern;public class TestInitOnlyOne {private boolean isInitialized = false;public synchronized void init() {if(isInitialized) {return;}doInit();isInitialized = true;}private void doInit() {// 初始化操作}}
?4、Balking Pattern是警戒条件不成立的时候立即退出,而生产者消费者模式则是一直等待警戒条件成立才继续执行。二者都是一种极端。有时候可以采用折中的timeout模式,timeout模式为当警告条件不成立的时候则选择等待一段时间,若期间成立了则继续执行,若还没有成立则退出
可以使用wait(10000);timeout结束的条件:nofity()/nofityAll(),作用于实例timeout时间到了调用了该线程interrupt()方法,获取锁定后抛出异常,作用于线程

5、判定结束是由上述哪种情况结束的,(timeout如何结束)

?

?

package com.metarnet.BalkingPattern;/** * 创建了超时的异常,继承了InterruptedException * 超时后抛出异常并打印信息 * @author Administrator * */public class TimeOutException extends InterruptedException {public TimeOutException(String msg) {super(msg);}}
package com.metarnet.BalkingPattern;/** * 主类,设置了超时时间,在测试主方法里面没有调用setExecutable修改警戒条件,当超时时抛出TimeOutException * @author Administrator * */public class TimeOut {private final long timeout;private boolean isReady = false;public TimeOut(boolean isReady, long timeout) {super();this.isReady = isReady;this.timeout = timeout;}public synchronized void setExecutable(boolean on) {isReady = on;this.notifyAll();}public synchronized void execute() throws TimeOutException, InterruptedException {long start = System.currentTimeMillis();while(!isReady) {long now = System.currentTimeMillis();long temp = timeout - (now - start);if(temp <= 0) { throw new TimeOutException("now - start = " + (now - start) + ", timeout = " + timeout);}wait(temp);}doExecute();}private void doExecute() {System.out.println(Thread.currentThread().getName() + " is do parse !");}}
package com.metarnet.BalkingPattern;public class TestTimeoutMain {public static void main(String[] args) {TimeOut test = new TimeOut(false, 10000);System.out.println("doexcute begin...");try {test.execute();} catch (TimeOutException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
?

?

读书人网 >编程

热点推荐