使用观察者模式实现线程将计算结果回调给多个对象
2017-07-03 10:40
609 查看
《Java网络编程》第三章线程讲使用回调的方法从线程中返回信息给对象。例如,如果有多个对象对线程的计算结果感兴趣,那么线程可以保存一个要回调的对象列表。特定的对象可以通过调用线程类的一个方法把自己添加到这个列表中来完成注册,表示自己对计算结果很感兴趣。如果有多个类的实例对结果感兴趣,可以定义一个新的Observer interface (接口),所有这些类都要实现这个新接口。这个Observer interface(接口)将声明回调方法。以上是观察者模式的典型应用场景。
接下来将上面的需求实现。
接下来将上面的需求实现。
1. Observer接口
声明回调方法updateinterface Observer { void update(byte[] digest); }
2. 感兴趣的观察者InstanceCallbackDigestUserInterface01
其中将通知者作为其成员变量public class InstanceCallbackDigestUserInterface01 implements Observer { static Logger logger = LoggerFactory.getLogger(InstanceCallbackDigestUserInterface01.class); private String filename; private byte[] digest; public InstanceCallbackDigestUserInterface01(String filename) { this.filename = filename; } @Override public String toString() { String result = filename + ": "; if (digest != null) { result += DatatypeConverter.printHexBinary(digest); } else { result += "digest not available"; } return result; } @Override public void update(byte[] digest) { this.digest = digest; //只是显示摘要,但功能更强的类还可以完成其他操作 //如将摘要存储在一个字段中,用它启动另一个钱程,或者对它完成进一步的计算。 logger.info(this.toString()); } }
3. 感兴趣的观察者InstanceCallbackDigestUserInterface02以及新线程任务SaveDatabase
public class InstanceCallbackDigestUserInterface02 implements Observer { Logger logger = LoggerFactory.getLogger(InstanceCallbackDigestUserInterface02.class); byte[] digest = null; @Override public void update(byte[] digest) { logger.info("interface02 get this digest"); this.digest = digest; ExecutorService exec = Executors.newCachedThreadPool(); exec.submit(new SaveDatabase(digest)); } } class SaveDatabase implements Runnable { Logger logger = LoggerFactory.getLogger(SaveDatabase.class); private byte[] digest; public SaveDatabase(byte[] digest){ this.digest = digest; } @Override public void run() { String s = DatatypeConverter.printHexBinary(digest); logger.info(s); } }
4. 通知者InstanceCallbackDigest
保存一个要回调的对象列表callback。特定的对象可以通过调用attach方法把自己添加到这个列表中来完成注册public class InstanceCallbackDigest implements Runnable { Logger logger = LoggerFactory.getLogger(InstanceCallbackDigest.class); private String filename; private LinkedHashSet<Observer> callback = new LinkedHashSet<>(); public InstanceCallbackDigest(String filename) { this.filename = filename; } public void attach(Observer observer) { callback.add(observer); } public void detach(Observer observer) { callback.remove(observer); } @Override public void run() { try { FileInputStream in = new FileInputStream(filename); MessageDigest sha = MessageDigest.getInstance("SHA-256"); DigestInputStream din = new DigestInputStream(in, sha); while (din.read() != -1) ; // read entire file din.close(); byte[] digest = sha.digest(); for (Observer o:callback ) { logger.info("callback update"); o.update(digest); } } catch (IOException | NoSuchAlgorithmException ex) { System.err.println(ex); } } }
5. Test类
public class Test { static Logger logger = LoggerFactory.getLogger(Test.class); public void calculateDigest(String filename, LinkedHashSet<Observer> callback) { InstanceCallbackDigest cb = new InstanceCallbackDigest(filename); //注册 for (Observer o : callback ) { cb.attach(o); } Thread t = new Thread(cb); t.start(); } @org.junit.Test public void test () { logger.info("main线程"); String[] strs = new String[]{"bw01.txt","pom.xml"}; // String[] strs = new String[]{"bw01.txt"}; for (String filename : strs) { //注册 InstanceCallbackDigestUserInterface01 d = new InstanceCallbackDigestUserInterface01(filename); InstanceCallbackDigestUserInterface02 interface02 = new InstanceCallbackDigestUserInterface02(); LinkedHashSet<Observer> callback = new LinkedHashSet<>(); callback.add(d); callback.add(interface02); //启动了线程 calculateDigest(filename, callback); //如何通知主线程子线程结束? try { TimeUnit.SECONDS.sleep(3l); } catch (InterruptedException e) { e.printStackTrace(); } } } }
6. 类图
7. 运行结果
相关文章推荐
- WCF中使用观察者模式实现事件通知
- 观察者模式使用WebForm实现的例子
- 观察者模式(Observer Pattern)(三):使用java内置的支持实现HeadFirst气象站
- 使用MATLAB实现计算结果的图形表示
- 使用 javascript 来实现 观察者模式
- 翻译:观察者模式—使用JavaScript实现
- 在C++中使用事件回调机制(通过Observer模式、函数指针等实现)
- 使用事件对象实现线程间的同步
- 使用UnrealScript实现基于观察者模式的事件系统
- 以【猫叫、老鼠跑、主人醒】为例子,使用 javascript 来实现 观察者模式 (有在线演示)
- 使用观察者模式实现Java应用程序设计MVC模式
- 03使用jdk提供类实现观察者模式(三)
- C#中使用委托和事件实现观察者模式(observer pattern)
- 使用观察者(Observer)实现对象监听 (转自http://blog.csdn.net/kalex)
- 如何使用委托与事件来实现观察者模式
- 多线程---使用ManualResetEvent来控制线程间的同步(实现了消费者和生产者模式)
- 翻译:观察者模式—使用JavaScript实现(转)
- QuteCom手记:使用Event类实现观察者模式
- 观察者模式使用C#实现
- 多线程异步编程(2):创建多个线程执行任务,同时更新进度条,使用观察者模式,利用事件通知界面更新。移除对Form的引用,彻底解除界面与逻辑的耦合