From: John B. Matthews on
In article <S9Sln.90254$Ye4.78776(a)newsfe11.iad>,
Knute Johnson <nospam(a)rabbitbrush.frazmtn.com> wrote:

> On 3/10/2010 10:34 AM, markspace wrote:
> > Knute Johnson wrote:
> >> Does anybody know if the Observable/Observer calls to update() are on
> >> the EDT?
>
> > Considering that Observer is just an interface and it would depend
> > on the implementation, and that no Java Swing classes that I know
> > of actually implement Observer, I'd have to guess the answer is in
> > general "no."
>
> The Observable class method, notifyObservers() is called and that
> then calls all Observer.update() methods. I'm curious to know if the
> Observable puts those calls onto the EDT.

As markspace has elaborated, the answer is no. Not long ago, I proposed
that on Observable can invoke notifyObservers() on the EDT, as via
javax.swing.Timer, but access to any data shared between threads must
still be correctly synchronized. I found this discussion very helpful

<http://groups.google.com/group/comp.lang.java.programmer/browse_frm/thread/4c4a6b46ffd2d31f>

and I have tried to express my understanding in this example:

<http://sites.google.com/site/drjohnbmatthews/threadwatch>

--
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>
From: Knute Johnson on
On 3/10/2010 3:07 PM, John B. Matthews wrote:
> In article<S9Sln.90254$Ye4.78776(a)newsfe11.iad>,
> Knute Johnson<nospam(a)rabbitbrush.frazmtn.com> wrote:
>
>> On 3/10/2010 10:34 AM, markspace wrote:
>>> Knute Johnson wrote:
>>>> Does anybody know if the Observable/Observer calls to update() are on
>>>> the EDT?
>>
>>> Considering that Observer is just an interface and it would depend
>>> on the implementation, and that no Java Swing classes that I know
>>> of actually implement Observer, I'd have to guess the answer is in
>>> general "no."
>>
>> The Observable class method, notifyObservers() is called and that
>> then calls all Observer.update() methods. I'm curious to know if the
>> Observable puts those calls onto the EDT.
>
> As markspace has elaborated, the answer is no. Not long ago, I proposed
> that on Observable can invoke notifyObservers() on the EDT, as via
> javax.swing.Timer, but access to any data shared between threads must
> still be correctly synchronized. I found this discussion very helpful
>
> <http://groups.google.com/group/comp.lang.java.programmer/browse_frm/thread/4c4a6b46ffd2d31f>
>
> and I have tried to express my understanding in this example:
>
> <http://sites.google.com/site/drjohnbmatthews/threadwatch>
>

I looked through the source code and all of the methods of Observable
are synchronized on the Observable instance. So threads that read any
argument that is passed in and stored needs to be synchronized as well.
I'm not sure how to do that. The whole point of using
Observer/Observable is to disconnect the two classes.

Calling notifyObservers() from a known thread could be used to
synchronize via thread containment but the docs imply that the calling
thread isn't necessarily guaranteed to be the writing thread in the future.

In the application that I am writing, I am passing an Integer). In the
Observer.update() method I store that Integer. I'm storing it in a
volatile int so that solves the visibility problems for the reading
thread but what if you had a mutable Object to pass?

Thanks,

--

Knute Johnson
email s/nospam/knute2010/

From: John B. Matthews on
In article <WXWln.10092$QL4.95(a)newsfe24.iad>,
Knute Johnson <nospam(a)rabbitbrush.frazmtn.com> wrote:

> On 3/10/2010 3:07 PM, John B. Matthews wrote:
> > In article<S9Sln.90254$Ye4.78776(a)newsfe11.iad>,
> > Knute Johnson<nospam(a)rabbitbrush.frazmtn.com> wrote:
> >
> >> On 3/10/2010 10:34 AM, markspace wrote:
> >>> Knute Johnson wrote:
> >>>> Does anybody know if the Observable/Observer calls to update() are on
> >>>> the EDT?
> >>
> >>> Considering that Observer is just an interface and it would
> >>> depend on the implementation, and that no Java Swing classes that
> >>> I know of actually implement Observer, I'd have to guess the
> >>> answer is in general "no."
> >>
> >> The Observable class method, notifyObservers() is called and that
> >> then calls all Observer.update() methods. I'm curious to know if
> >> the Observable puts those calls onto the EDT.
> >
> > As markspace has elaborated, the answer is no. Not long ago, I
> > proposed that on Observable can invoke notifyObservers() on the
> > EDT, as via javax.swing.Timer, but access to any data shared
> > between threads must still be correctly synchronized. I found this
> > discussion very helpful
> >
> > <http://groups.google.com/group/comp.lang.java.programmer/browse_frm/thread/4c4a6b46ffd2d31f>
> >
> > and I have tried to express my understanding in this example:
> >
> > <http://sites.google.com/site/drjohnbmatthews/threadwatch>
>
> I looked through the source code and all of the methods of Observable
> are synchronized on the Observable instance. So threads that read
> any argument that is passed in and stored needs to be synchronized as
> well. I'm not sure how to do that. The whole point of using
> Observer/Observable is to disconnect the two classes.

Interesting. The synchronized block in notifyObservers() mentions two,
worst-case potential races: 1) a newly-added Observer will miss a
notification in progress, and 2) a recently unregistered Observer will
be wrongly notified when it doesn't care. Unfortunately, the API doesn't
mention being synchronized.

> Calling notifyObservers() from a known thread could be used to
> synchronize via thread containment but the docs imply that the
> calling thread isn't necessarily guaranteed to be the writing thread
> in the future.

I read the Observable API as "but subclasses [of Observable] may ...
deliver notifications on separate threads."

> In the application that I am writing, I am passing an Integer). In
> the Observer.update() method I store that Integer. I'm storing it in
> a volatile int so that solves the visibility problems for the reading
> thread but what if you had a mutable Object to pass?

I'm not sure about that.

--
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>
From: Peter Duniho on
Knute Johnson wrote:
> I looked through the source code and all of the methods of Observable
> are synchronized on the Observable instance.

The class has been around since 1.0. I suspect the synchronization was
simply part of a misguided attempt to provide generally thread-safe
classes, a la Vector.

> So threads that read any
> argument that is passed in and stored needs to be synchronized as well.
> I'm not sure how to do that. The whole point of using
> Observer/Observable is to disconnect the two classes.

As the docs make clear, the Observable class is specifically _not_ about
threading. It's every bit as useful in a single-threaded program, but
of course if you choose to call notifyObservers() in a thread other than
the one where handling of data in the update() method should be done
(e.g. EDT issues), or the update() method will be touching data that
needs to be synchronized between other threads, that would be up to your
Observer implementation to handle.

That said…

> Calling notifyObservers() from a known thread could be used to
> synchronize via thread containment but the docs imply that the calling
> thread isn't necessarily guaranteed to be the writing thread in the future.

What the docs seem to imply to me is that while the default
implementation of Observable simply calls the update() method for all
the Observers, that sub-classes may have arbitrarily different behavior.

Of course, this is a strong hint that if you would like your update()
methods to be invoked on the EDT, that one obvious approach would be to
write an Observable sub-class that does in fact do that.

> In the application that I am writing, I am passing an Integer).

Passing an Integer to what? The notifyObservers() method? Something else?

I note that in many situations, one might find that it makes sense for a
data container object to inherit Observable directly, such that no other
data reference need be passed to the notifyObservers() method (and the
update() method would get "null" for the "arg" parameter). Note the
language in the documentation, in which it describes the "change" as
happening to the Observable itself, as opposed to some other object.

Of course, you can provide an object in the notifyObservers() call, but
then that means your own code needs to keep track of which Observable
goes with which mutable state/data. A reasonable alternative IMHO would
be for your Observable itself to be what's changed.

(In fact, I'm a little surprised that there's not an equivalent
interface to go with Observable; it makes sense for a default
implementation to be provided, but what about other types that might
also want to be "observable" but which for other reasons can't inherit
Observable? They're going to wind up with some kind of de facto
"observable" interface anyway…might as well publish one in the JDK :) ).

> In the
> Observer.update() method I store that Integer. I'm storing it in a
> volatile int so that solves the visibility problems for the reading
> thread but what if you had a mutable Object to pass?

If the mutable Object was thread-safe, then it would handle that.
Otherwise, you'd have to use some mechanism for ensuring
synchronization. As far as I know, Java doesn't have an explicit memory
barrier API, so "synchronized" is probably the best approach for simple
mutation observability issues.

Pete
From: Knute Johnson on
On 3/10/2010 8:48 PM, Peter Duniho wrote:
> If the mutable Object was thread-safe, then it would handle that.
> Otherwise, you'd have to use some mechanism for ensuring
> synchronization. As far as I know, Java doesn't have an explicit memory
> barrier API, so "synchronized" is probably the best approach for simple
> mutation observability issues.
>
> Pete

And there's the rub. If you have as in my case, two separate classes,
where you don't want to share data other than that which is shared via
the Observable/Observer, how do you get the Observable instance in the
Observer to then use to synchronize with? You have to assume that a
different thread could read the data after it was stored via the
Observer.update() method.

--

Knute Johnson
email s/nospam/knute2010/

First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5 6 7
Prev: Exception Handling
Next: First class developer: who ?