- 浏览: 746438 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (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 1626local class的scope是local,所以在方法 ... -
URL definition
2012-08-14 08:29 7279http://reg.163.com/login.jsp?ty ... -
how to defend against serialization and reflection attack for eager singleton
2012-08-08 09:18 1299//为什么要定义构造方法 因为不定义它也会有默认构造方法,而 ... -
Finalizer Guardian Idiom
2012-05-30 11:55 1312Effective Java 2nd 中Item 7: A ... -
我對多態的理解
2012-05-24 09:03 1069多态(polymorphism)是以一种看待事物更细致的角度来 ... -
Bridge Pattern
2011-06-17 11:59 838Intent Decouple an abstracti ... -
Composite Pattern
2011-06-17 09:12 964http://userpages.umbc.edu/~ta ... -
Observer Pattern
2011-06-15 11:32 1090consistent communication model ... -
Factory Method
2011-05-27 23:46 1004how does the factory method pat ... -
Law of Demeter
2011-04-07 09:23 1059http://en.wikipedia.org/wiki/La ... -
Several thread-safe singleton collection
2011-02-24 10:19 10351. static inner class publi ... -
关于Arrays.sort()方法用到的设计模式
2011-02-18 09:12 2887/** * Src is the sour ... -
何时使用LSP
2011-01-24 09:12 1015当使用subclass无法满足LSP(Liskov Subst ... -
Command模式图详解
2011-01-12 16:53 968上图是command模式结构图,各个符号重点应该理解,符 ... -
IOC inversion体现在什么地方
2011-01-12 16:02 1068http://martinfowler.com/bliki/I ... -
什么时候需要synchronized
2010-12-02 15:32 1168当需要在某个方法上加synchronized关 ... -
多任务同时执行完毕后方执行后续任务
2010-12-02 10:20 1226多线程同时启动,执行完毕后启动新任务 1.传统join ... -
Apache Struts2 Architecture
2010-07-21 22:38 978Struts is a flexible control la ... -
开闭原则
2010-03-15 13:58 970Closed for Modification; Op ... -
多态之RTTI
2010-01-21 16:58 1397所谓RTTI,是Runtime Type Informatio ...
相关推荐
Java线程池是Java并发编程中的重要组成部分,它...总之,通过Java线程池和观察者模式的结合,我们可以构建一个健壮的多线程系统,即使在部分线程意外终止的情况下,也能及时发现并采取措施恢复,确保系统的稳定运行。
在软件开发中,设计模式是一种经过时间和实践验证的解决方案,用于解决常见的编程问题。Qt库,作为一个跨平台的C++图形用户...无论是简单的用户界面交互,还是复杂的多线程数据同步,观察者模式都能提供有力的支持。
观察者模式(Observer Pattern)是设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。这种模式在软件工程中广泛应用,特别是...
7. **其他变体**:除了基本的观察者模式,还有复合观察者模式,允许一个观察者对象包含多个观察者,以及异步观察者模式,通知过程在不同的线程中执行,以避免阻塞主线程。 在实际开发中,理解并熟练运用观察者模式...
在多线程环境下,一个线程完成任务后,可以通过观察者模式通知其他线程进行下一步操作。 观察者模式在Java中得到了很好的支持,`java.util.Observable`和`java.util.Observer`是Java标准库提供的观察者模式实现。...
在多线程编程中,观察者模式常用于监控线程的状态,以便在特定时刻进行相应的操作。下面将详细解释如何使用观察者模式来跟踪和管理线程的生命周期。 首先,我们需要定义一个表示任务生命周期的枚举类型接口`...
观察者模式在C++中的应用非常广泛,例如GUI编程中的事件处理、多线程通信、日志系统等。它提供了一种松耦合的方式,使得主题和观察者之间可以独立地进行扩展和修改,增强了系统的灵活性和可维护性。
在实际应用中,观察者模式广泛应用于事件处理、用户界面、多线程通信等领域。例如,Java的`java.util.Observable`和`java.util.Observer`类就是观察者模式的一个实现,用于事件驱动编程。另外,许多现代框架,如...
4. **案例分析**:通过实际案例,如用户界面控件的事件处理、多线程环境下的消息传递等,深入分析观察者模式的应用场景和优势,同时讨论可能遇到的问题和解决策略。 5. **扩展与变体**:书籍可能会讨论一些观察者...
观察者模式,也被称为发布-订阅(Publish-Subscribe)模式,是软件设计模式中的行为模式之一,主要用于定义对象之间的依赖关系。当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式是...
观察者模式是软件设计模式中的一种行为模式,它在对象之间定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式广泛应用于事件处理、发布订阅系统、消息...
观察者模式是一种设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的...在实际项目中,如UI界面的事件处理、多线程编程中的回调机制等,都可以看到观察者模式和委托的广泛运用。
本篇将深入探讨如何利用多线程技术以及观察者模式来解决这个问题。 首先,多线程是Android中处理耗时操作的关键技术。在ListView中,如果每个条目都直接进行网络下载,会占用主线程(UI线程)资源,使得界面无法...
观察者模式的概念与结构 - **主题(Subject)**:它是被观察的对象,通常包含两个接口,一是`addObserver()`用于添加观察者,二是`removeObserver()`用于移除观察者。同时,它还有一个`notifyObservers()`方法,...
2. **观察者模式**:在多线程环境中,观察者模式常用于实现线程间的通信,其中一个对象(主题)的状态改变时会通知所有依赖于它的观察者对象,使得它们能够自动更新自己的状态。 3. **职责链模式**:这种模式可以...
观察者模式是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式广泛应用于事件处理、发布/订阅系统等。在Java中,可以使用`...
在这个场景中,我们关注的是如何使用观察者模式(Observer Pattern)来实现Activity A和C之间的数据交互。观察者模式是一种行为设计模式,它允许一个对象(观察者)在另一个对象(被观察者)的状态改变时自动收到...
5. **应用场景**:观察者模式广泛应用于各种领域,如用户界面的事件处理、多线程同步、消息队列等。例如,在GUI编程中,当用户点击按钮时,按钮对象作为主题,可以通知所有关联的观察者(如窗口、菜单等)进行相应...
《观察者模式——深入解析与应用》 观察者模式(Observer Pattern)是设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种...
在多线程环境下,观察者模式可以被巧妙地应用于子线程通知主线程的情况。 观察者模式的核心思想是定义一个一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。在Java中,`...