- 浏览: 728353 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (419)
- 杂软粉墨 (2)
- 创意灵感 (3)
- 经验记录 (137)
- 开源轨迹 (2)
- sip-communicator (2)
- 闲侃杂谈 (8)
- 问题交流 (24)
- 概念模式 (32)
- 难点备案 (5)
- JwChat (1)
- 中国象棋 (1)
- 教育探索 (6)
- 英语研究 (58)
- 星际争霸 (1)
- 电信知识 (1)
- 软件架构 (3)
- 哲学探索 (26)
- 算法灵魂 (8)
- 近视探索 (6)
- 数学数学 (3)
- 牛角钻尖 (23)
- 至强文言 (3)
- 数据结构 (1)
- 宇宙物理 (2)
- 网络架构 (3)
- 游戏领域 (4)
- 图形处理 (2)
- 修炼之路 (8)
- 读书天地 (20)
- 编解乱码 (2)
- 概念探索 (8)
- 格物致知 (1)
- 其它语言 (1)
- 测试领域 (3)
- 文化风流 (1)
- JQuery (1)
- 網頁領域 (1)
- Unix/Linux (1)
- Inside JVM (1)
- 异常分析 (1)
最新评论
-
suyujie:
引用
HTML <a> 标签灰显禁用 -
suyujie:
HTML <a> 标签灰显禁用 -
suyujie:
HTML <a> 标签灰显禁用 -
suyujie:
HTML <a> 标签灰显禁用 -
iamzhoug37:
您能说一下"局部变量不受文本顺序限制" 是 ...
声明前为什么能赋值却不能输出,都是使用
观察者模式是很常用、常见当然也相当重要的一种设计模式,其中主要包括的概念有:
1.Observer(观察者,又具化作ActionListener)
2.Observable(被观察者)
3.Action(观察者所感兴趣的被观察者的行为)
被观察者主动与观察者建立契约关系(添加观察者),观察者本身具有行为发生被告知资格,即拥有行为响应方法,如actionPerformed,下面贴出一段程序:
import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; // Broken - invokes alien method from synchronized block! public class ObservableSet<E> extends ForwardingSet<E> { public ObservableSet(Set<E> set) { super(set); } private final List<SetObserver<E>> observers = new ArrayList<SetObserver<E>>(); public void addObserver(SetObserver<E> observer) { synchronized (observers) { observers.add(observer); } } public boolean removeObserver(SetObserver<E> observer) { synchronized (observers) { return observers.remove(observer); } } private void notifyElementAdded(E element) { synchronized (observers) { for (SetObserver<E> observer : observers) observer.added(this, element); } } @Override public boolean add(E element) { boolean added = super.add(element); if (added) notifyElementAdded(element); return added; } @Override public boolean addAll(Collection<? extends E> c) { boolean result = false; for (E element : c) result |= add(element); // calls notifyElementAdded return result; } }
public interface SetObserver<E> { // Invoked when an element is added to the observable set void added(ObservableSet<E> set, E element); }
import java.util.Collection; import java.util.Iterator; import java.util.Set; // Reusable forwarding class public class ForwardingSet<E> implements Set<E> { private final Set<E> s; public ForwardingSet(Set<E> s) { this.s = s; } public void clear() { s.clear(); } public boolean contains(Object o) { return s.contains(o); } public boolean isEmpty() { return s.isEmpty(); } public int size() { return s.size(); } public Iterator<E> iterator() { return s.iterator(); } public boolean add(E e) { return s.add(e); } public boolean remove(Object o) { return s.remove(o); } public boolean containsAll(Collection<?> c) { return s.containsAll(c); } public boolean addAll(Collection<? extends E> c) { return s.addAll(c); } public boolean removeAll(Collection<?> c) { return s.removeAll(c); } public boolean retainAll(Collection<?> c) { return s.retainAll(c); } public Object[] toArray() { return s.toArray(); } public <T> T[] toArray(T[] a) { return s.toArray(a); } @Override public boolean equals(Object o) { return s.equals(o); } @Override public int hashCode() { return s.hashCode(); } @Override public String toString() { return s.toString(); } }
下面是测试类:
import java.util.HashSet; public class Test { public static void main(String[] args) { ObservableSet<Integer> set = new ObservableSet<Integer>(new HashSet<Integer>()); set.addObserver(new SetObserver<Integer>() { public void added(ObservableSet<Integer> s, Integer e) { System.out.println(e); } }); for (int i = 0; i < 100; i++) set.add(i); } }
如此便有了一个观察者模式的简单示例,但如果往测试类中加一句:
import java.util.HashSet; public class Test { public static void main(String[] args) { ObservableSet<Integer> set = new ObservableSet<Integer>(new HashSet<Integer>()); set.addObserver(new SetObserver<Integer>() { public void added(ObservableSet<Integer> s, Integer e) { System.out.println(e); if (e == 23) s.removeObserver(this); } }); for (int i = 0; i < 100; i++) set.add(i); } }
会发现,报以下错误:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at ObservableSet.notifyElementAdded(ObservableSet.java:28)
at ObservableSet.add(ObservableSet.java:37)
at Test.main(Test.java:14)
The problem is that notifyElementAdded is
in the process of iterating over the observers list when it invokes the observer’s
added method. The added method calls the observable set’s removeObserver
method, which in turn calls observers.remove. Now we are in trouble. We are
trying to remove an element from a list in the midst of iterating over it, which is
illegal. The iteration in the notifyElementAdded method is in a synchronized
block to prevent concurrent modification, but it doesn’t prevent the iterating thread
itself from calling back into the observable set and modifying its observers list.
问题是以下两个方法被同时调用了,当然是同一个线程,所以synchronized关键字对这种行为无效:
public boolean removeObserver(SetObserver<E> observer) { synchronized (observers) { return observers.remove(observer); } } private void notifyElementAdded(E element) { synchronized (observers) { for (SetObserver<E> observer : observers) observer.added(this, element); } }
问题本质是遍历线程对在处于遍历操作中的List进行remove操作,但改成如下又会造成死锁:
// Observer that uses a background thread needlessly set.addObserver(new SetObserver<Integer>() { public void added(final ObservableSet<Integer> s, Integer e) { System.out.println(e); if (e == 23) { ExecutorService executor = Executors.newSingleThreadExecutor(); final SetObserver<Integer> observer = this; try { executor.submit(new Runnable() { public void run() { s.removeObserver(observer); } }).get(); } catch (ExecutionException ex) { throw new AssertionError(ex.getCause()); } catch (InterruptedException ex) { throw new AssertionError(ex.getCause()); } finally { executor.shutdown(); } } } });
The background thread
calls s.removeObserver, which attempts to lock observers, but it can’t acquire
the lock, because the main thread already has the lock. All the while, the main
thread is waiting for the background thread to finish removing the observer, which
explains the deadlock.
但这样就不会造成死锁:
import java.util.HashSet; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test { public static void main(String[] args) { ObservableSet<Integer> set = new ObservableSet<Integer>(new HashSet<Integer>()); // Observer that uses a background thread needlessly set.addObserver(new SetObserver<Integer>() { public void added(final ObservableSet<Integer> s, Integer e) { System.out.println(e); if (e == 23) { ExecutorService executor = Executors.newSingleThreadExecutor(); final SetObserver<Integer> observer = this; try { executor.submit(new Runnable() { public void run() { s.removeObserver(observer); } }); } finally { executor.shutdown(); } } } }); for (int i = 0; i < 100; i++) { set.add(i); } } }
原因应该是backgroud thread在竞争锁时能等待main thread执行完毕(其不阻塞),但也不会打印完整100个数,因为observer会被remove,再调用notifyElementAdded自然也就没有意义,当然原来的方法改变notifyElementAdded也不会造成死锁:
// Alien method moved outside of synchronized block - open calls private void notifyElementAdded(E element) { List<SetObserver<E>> snapshot = null; synchronized(observers) { snapshot = new ArrayList<SetObserver<E>>(observers); } for (SetObserver<E> observer : snapshot) observer.added(this, element); }
还有更好的方法:
// Thread-safe observable set with CopyOnWriteArrayList private final List<SetObserver<E>> observers = new CopyOnWriteArrayList<SetObserver<E>>(); public void addObserver(SetObserver<E> observer) { observers.add(observer); } public boolean removeObserver(SetObserver<E> observer) { return observers.remove(observer); } private void notifyElementAdded(E element) { for (SetObserver<E> observer : observers) observer.added(this, element); }
In fact, there’s a better way to move the alien method invocations out of the
synchronized block. Since release 1.5, the Java libraries have provided a concurrent
collection (Item 69) known as CopyOnWriteArrayList, which is tailor-made
for this purpose. It is a variant of ArrayList in which all write operations are
implemented by making a fresh copy of the entire underlying array. Because the
internal array is never modified, iteration requires no locking and is very fast. For
most uses, the performance of CopyOnWriteArrayList would be atrocious, but
it’s perfect for observer lists, which are rarely modified and often traversed.
应该是创造了在遍历过程中不会被它线程更改数组结构的机制,而在遍历后或再次遍历时能将写效果实现于读效果之上
发表评论
-
java语言中classes分类
2012-10-22 13:09 1584local class的scope是local,所以在方法 ... -
URL definition
2012-08-14 08:29 7229http://reg.163.com/login.jsp?ty ... -
how to defend against serialization and reflection attack for eager singleton
2012-08-08 09:18 1225//为什么要定义构造方法 因为不定义它也会有默认构造方法,而 ... -
Finalizer Guardian Idiom
2012-05-30 11:55 1274Effective Java 2nd 中Item 7: A ... -
我對多態的理解
2012-05-24 09:03 1025多态(polymorphism)是以一种看待事物更细致的角度来 ... -
Bridge Pattern
2011-06-17 11:59 790Intent Decouple an abstracti ... -
Composite Pattern
2011-06-17 09:12 914http://userpages.umbc.edu/~ta ... -
Observer Pattern
2011-06-15 11:32 1051consistent communication model ... -
Factory Method
2011-05-27 23:46 943how does the factory method pat ... -
Law of Demeter
2011-04-07 09:23 1015http://en.wikipedia.org/wiki/La ... -
Several thread-safe singleton collection
2011-02-24 10:19 9951. static inner class publi ... -
关于Arrays.sort()方法用到的设计模式
2011-02-18 09:12 2848/** * Src is the sour ... -
何时使用LSP
2011-01-24 09:12 979当使用subclass无法满足LSP(Liskov Subst ... -
Command模式图详解
2011-01-12 16:53 931上图是command模式结构图,各个符号重点应该理解,符 ... -
IOC inversion体现在什么地方
2011-01-12 16:02 1037http://martinfowler.com/bliki/I ... -
什么时候需要synchronized
2010-12-02 15:32 1136当需要在某个方法上加synchronized关 ... -
多任务同时执行完毕后方执行后续任务
2010-12-02 10:20 1181多线程同时启动,执行完毕后启动新任务 1.传统join ... -
Apache Struts2 Architecture
2010-07-21 22:38 910Struts is a flexible control la ... -
开闭原则
2010-03-15 13:58 928Closed for Modification; Op ... -
多态之RTTI
2010-01-21 16:58 1360所谓RTTI,是Runtime Type Informatio ...
相关推荐
Java线程池及观察者模式解决多线程意外死亡重启问题,附件含两个要运行代码!
多线程下载,包括暂停、继续下载、取消; 使用观察者模式进行针对更新,防止ListView下载进度乱串
用观察者模式设计一个交通信号灯调度系统,有需要的朋友可以参考下。这是本人写一篇有关于Java中设计模式,多线程调度的一个Demo吧,本人水平有限,望各位博友批评指正。此Demo实现了现实交通信号灯调度车辆通行的功能,...
背景:当线程在运行的时候,如果没有使用线程池等包的时候,那么直接newThread这种方法的话,是很难观察到线程目前的状态的,如果知道当前这个线程是运行还是停止
Android 基于观察者模式下载管理 断点续传 ,多线程管理 ,listView item,RecycleView item 刷新
主要介绍了Java设计模式—观察者模式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
6:使用状态模式 观察者模式更好的处理多线程 最初的想法:网络优化开发框架 (移除任务未完成) 网络稳定,系统运行稳定性,大内存消耗稳定,长时间运行稳定性 (旧的系统症结所在) 开启过多线程,导致系统...
22.4.1 Java世界中的观察者模式 22.4.2 项目中真实观察者模式 22.4.3 订阅发布模型 22.5 最佳实践 第23章 门面模式 23.1 我要投递信件 23.2 门面模式的定义 23.3 门面模式的应用 23.3.1 门面模式的优点 23.3.2 门面...
由三个类实现,写在了一个 Java 文件中:...代码中运用了命令模式,如若能配以监听器,用上观察者模式来控制 UI 显示就更绝妙不过了,就能实现像下载中的区块着色跳跃的动感了,在此定义下一步的着眼点了。
没使用观察者模式,而是尝试启动多个线程来完成帧更新,数据读取和数据显示 水平有限,多多包涵
4.6 OBSERVER 观察者模式 83 4.7 MEMENTO 备忘录模式 87 4.8 STATE 状态模式 91 4.9 STRATEGY 策略模式 96 4.10 TEMPLATE METHOD模板方法 100 4.11 VISITOR 访问者模式 103 C++高级编程 108 5.1 多态及其实现机制 ...
9 观察者模式 10 内部类讲解 11 JAVA I/O流讲解 12 JAVA多线程 13 JAVA网络通信 14 JAVA类加载器CLASSLOADER 15 JAVA简单工厂模式 16 JAVA中的注解 17 JAVA 图形界面 18 JAVA多线程 19 JAVA 反射机制 20 ...
IO流高级 设计模式 多线程 网络编程 struts2 注解 反射 MVC+Log4 资源文件 泛型 观察者模式 装饰模式
5.7ObserverPattern(观察者模式) 236 5.7.1定义 236 5.7.2现实例子——拉登现身了 238 5.7.3C#实例——猫和老鼠 238 5.7.4C#实例——股票变化 241 5.7.5Java实例——监控系统 245 5.7.6优势和缺陷 248 ...
设计模式: 探讨常见的设计模式,如工厂模式、单例模式、观察者模式等,以及如何在Python中应用这些模式。 测试和调试: 介绍高级的测试技术和调试工具,以确保代码的质量和可维护性。 性能优化: 提供关于Python...
涵含各种重要的JAVA编程知识点,面试突击专用 内容包括:Spring、SprngBoot、SpringCloud、Redis、MySQL、MyBatis、JVM、多...设计模式:包括常见的设计模式,如单例模式,工厂模式,观察者模式等,以及它们的使用场景
5.7ObserverPattern(观察者模式) 236 5.7.1定义 236 5.7.2现实例子——拉登现身了 238 5.7.3C#实例——猫和老鼠 238 5.7.4C#实例——股票变化 241 5.7.5Java实例——监控系统 245 5.7.6优势和缺陷 248 ...
观察者模式当您有一些对象必须将一个对象的状态更改通知所有感兴趣的对象时,将使用观察者模式。 在图形上,这是这样工作的: 下图是它的uml表示:让我们建立模型观察者接口可以使用以下结构构建: public interface...
Java面试题是针对Java编程语言的技术和知识的一系列问题,用于考察面试者在Java开发方面的能力和...设计模式:涉及常见的设计模式,如单例模式、工厂模式、观察者模式等。 Java框架和技术:包括Spring、Hibernate、My