2010-05-30 2 views
11

수신기 목록 (예 : Java에서 addXxxListener()removeXxxListener()을 사용하여 수신자를 등록 및 등록 취소)은 이고이며 일반적으로 Lists으로 구현됩니까? 청취자의 경우가Listener가 List를 나열하는 이유는 무엇입니까?

  • 아니라 이러한 요구가있을 수 있지만, 그들이 (전화를받을 어떤 순서에 상관없이을의 그러나 특별한 경우에있어 이후 Set가 더 적합하지 않을까요, 일반 청취자 메커니즘) 그러한 보증을하지 않으며,
  • 같은 청취자에게 1 회 또는 N 시간을 호출 발생한다 번 이상 (그 일을하는지 같은 리스너를 등록 또는 오류가 될 필요가 없습니다, 또 다른 질문)
입니다

전통에 불과합니까? 세트는 어쨌든 두피 내의 일종의 목록입니다. 성능 차이가 있습니까? 을 반복하는 것이 Set을 반복하는 것보다 빠르거나 느린가요? 어느 정도 메모리를 사용합니까? 차이점은 거의 무시할 수 있습니다.

+10

'그것이 list'ener 인 이유가 무엇입니까? : p – kennytm

답변

8

청취자 목록을 집합 대신 사용하는 중요한 이유 중 하나는 왜 거꾸로 반복되는 것을 자주 보는지 설명합니다. 일반적인 시나리오는 청취자가 변경 사항을 통보받을 때 자체를 청취자로 제거하는 것과 관련됩니다. 청취자가리스트로서 보존되어 순방향 반복 (또는 세트로서 포함되어있어 미정의 순서로 반복 처리되고있다) 인 경우, 청취자로서 자신을 삭제하면 (자), ConcurrentModificationException가 발생합니다.

그래서 대신 리스너가 목록으로 저장되고 역순으로 통지됩니다. 그런 다음 리스너가 통지 될 때 리스너 목록에서 자체를 제거하면 ConcurrentModificationException이 발생하지 않거나 아직 통지되지 않은 다른 리스너의 색인이 이동하지 않습니다.

+0

주문에 신경 쓰지 않는다면 어떨까요? –

+0

청취자가 통지를 받음에 따라 스스로 제거하는 경우주의를 기울여야합니다. 그렇지 않으면 주문을 보존하여 아무 것도 잃지 않았습니다. – Mark

+0

그들이 스스로 제거하면 왜 신경 써야합니까? 대부분의 경우, 세트를 사용하는 것이 좋습니다. 청취자는 일반적으로 다른 청취자와 비교하여 호출 될시기를 가정해서는 안됩니다. 어쩌면 SkipList가이 솔루션의 중간 단계일까요? 이상한, 나는 그것에 대한 Java 클래스를 찾을 수 없습니다. –

1

어떤 종류의 세트입니까? 모든 청취자가 해시 세트를 사용하도록 (듯이) equals 및 hashCode를 구현해야 할까, 또는 신원 해시 세트로 할까? 복잡성의 가치가있는 목록에 리스너를 추가 한 사례가 있습니까? 핸들러에 대한 호출 중에 리스너를 추가하거나 제거하는 것을 안전하게 설정하는 메커니즘이 있습니까?

성능 차이가있을 수 있지만 더 복잡한 디자인이있을 수 있으며 응용 프로그램에 두지 않고 여러 개의 다중 추가 제거 결정을 라이브러리에 적용해야합니다.

+0

신원 확인 해시 세트가 적절하다고 생각합니다. 그러나, "CopyOnWriteIdentityHashSet"은 사용 가능한 상태가 아니므로 공통 목록 관용구를 사용하면 올바른 최종 결과를 얻는 것이 더 간단 할 수 있습니다. –

+0

하지만 실제로는 Java 6에서 스레드 안전성 ("반복자를 통한 순회는 빠르며 다른 스레드의 간섭을받을 수 없음")의 CopyOnWriteArraySet이 있습니다. http://java.sun.com/javase/6/docs/technotes/guides/collections/changes5.html "이 구현은 중복을 방지해야하는 이벤트 핸들러 목록을 유지 관리하는 데 적합합니다." –

+1

@Joonas 스윙 스레드에서 Swing 핸들러가 호출 되었기 때문에 문제는 항상 기본 컬렉션을 수정하고 동시 업데이트가 아닌 반복기를 무효화하는 것이 었습니다. 그러나 이러한 의미를 원한다면 확실히 copy-on-write 세트를 사용할 수 있습니다. –

0

당신은 완전히 옳습니다. 리스너를 세트에 추가해야합니다. 말했듯이 한 번 이상 청취자를 추가하는 것은 의미가 없습니다. 또한 세트를 사용하는 경우 리스너의 순서에 의존하지 않습니다. 중요한 점은 소프트웨어 개발을 진지하게 생각하고 더 나은 설계를 이끌어 내기 위해 알아 낸 모든 원칙 (격리, 독립성, 책임)을 사용하면 안됩니다.

여기에 언급 된 모든 측면 (멀티 스레딩, 성능, ...)은 첫 번째 생각에서 자신을 종속시켜야하지만 좋은 이유가있는 경우에는 깨질 수 있습니다. 그리고 나는 아주 좋은 이유를 의미합니다.

그건 그렇고 : 청취자가 스스로 제거하게하는 것은 나쁜 습관입니다. 추가 및 제거는 대칭이어야합니다. 따라서 청취자는 등록 된 객체를 통해 제거되어야합니다. 많은 청취자가 참여한다면 곧 갇히게 될 것입니다.

관련 문제