views:

208

answers:

4

How can I check for a boolean to change state over a given period of time, and if a change is made over that time period perform a method?

Can any help please be given in Java.

Thanks.

+12  A: 

Sounds like you want to wrap a boolean in a class which you can listen for changes on.

class ObservableBoolean {

    // "CopyOnWrite" to avoid concurrent modification exceptions in loop below.
    private final List<ChangeListener> listeners =
            new CopyOnWriteArrayList<ChangeListener>();

    private boolean value;

    public boolean getValue() {
        return value;
    }

    public synchronized void setValue(boolean b) {
        value = b;
        for (ChangeListener cl : listeners)
            cl.stateChanged(new ChangeEvent(this));
    }

    public synchronized void addChangeListene(ChangeListener cl) {
        listeners.add(cl);
    }

    public synchronized void removeChangeListener(ChangeListener cl) {
        listeners.remove(cl);
    }
}

Then simply do:

ObservableBoolean b = new ObservableBoolean();

//...

// Start the "period of time":
b.addChangeListener(iWantToBeNotifiedOfChanges);

// ...

// End the "period of time":
b.removeChangeListener(iWantToBeNotifiedOfChanges);

This is actually a simple case of the MVC pattern (and the observer pattern). The model in this case is the ObservableBoolean and the view would be the "view" that want's to be notified of the changes.

You could also write your own ChangeListener interface if want to avoid a strange looking javax.swing... import

aioobe
+1 for observer pattern. I wonder whether you want to monitor the boolean itself, or if you should instead have the Class that is changing state own the listener list, and fire the change events when it performs the mod on the boolean.
akf
@aioobe -> see my edit now
Xorty
+1 ... but a few points: the listeners list should probably be final, getValue() is not synchronized, If a listener attempts to remove itself as a listener when notified this will lead to a ConcurrentModificationException. You could resolve this final problem by using a CopyOnWriteArrayList instead of ArrayList.
Adamski
Good point. One could also do new ArrayList<ChangeListener>(listeners) in the loop. What would you say are the pros'n'cons of those two solutions to the ConcurrentModificationException-problem?
aioobe
The main advantage of the CopyOnWriteArrayList approach is that you only take the hit of copying the list when adding / removing a listener, which is likely to be a far less common event than notifications.
Adamski
@aioobe: I think you should never notify while keeping a synchronization lock held. You don't know who's going to register hence you're basically making what is called an "alien method call". Never ever make an alien method while holding a synchronization lock.
Webinator
I would use `PropertyChangeListener` in the java.beans package, but same difference. Is there no way to avoid writing the `addChangeListener` and `removeChangeListener` methods? Also, couldn't this be parameterized (not with `boolean` but with `Boolean`)?
Yar
@WizardOfOdds very good point.@yar, sure. A bit of an overkill answer though ;)
aioobe
+1  A: 

use Timer or write your own class extending Thread.

Googling those things should give you good start

edit : From question it is not quite clear what are his intends. Maybe he wants to invoke some method in exact period of time, not immediatelly after event. For this pattern, I'd still rather stick to timer, or write my own Thread. Writing own Thread is still best way of interpreting specific user requirements. On the other hand, if this is really case of listening to events, my Timer pattern would be completely wrong.

example : I want to update database (imagine web browser game) every 5 minutes, if users requests so (reques = true). With false request, I don't need to update database. Immediatelly update database (f.e. stats in game Tribal Wars with thoushands of players) is totally overkill.

Xorty
A rapid changed from true -> false -> true would go unnoticed unless you wrap the boolean in some "check-if-changed-since-last-pall"-class.
aioobe
true, but question was not to check immediatelly but in certain amount of time (time period).It depends on model design.Extending Thread class is basically implementation of Listeners (not literally, but nearly same)
Xorty
"if a change is made over that time period perform a method". I'm saying, that if *two* changes are made over that time, you *do* need an extra boolean `stateHasChanged` that keeps track of this (otherwise it is quite possible that the change goes unnoticed).
aioobe
Too much IFs. You might be right, and might not. Piece of real code (not just theoretical questions) should solve this exactly.
Xorty
Are you a programmer? and two "IFs" are too much for you? ;-)
aioobe
@aioobe - indeed, did you read my example? your IFs fail there! there are no "two changes" ...
Xorty
This is a totally freaky answer, but strangely @Xorty is right: you could have a case where you want to poll with a timer. Though I cannot imagine any :)
Yar
A: 

Seems like you should look to implement some sort of Model View Controller Pattern. Have a look here

The basic idea is that you should fire an event when the boolean is changed, and then that event is fired, your listener should handle that.

Shervin
Ehm, why down vote??
Shervin
+5  A: 

The easiest way to do this is with a wrapper class...

public class Bool
{
    public Bool(){ _val = false; }
    public Bool(boolean val) { _val = val; }

    public boolean getValue(){ return _val; }
    public void setValue(boolean val){ 
         _changesupport.firePropertyChange("value",_val,_val=val);
    }

    public void addPropertyChangeListener(PropertyChangeListener listener ){
        _changesupport.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener){
        _changesupport.removePropertyChangeListener( listener );
    }

    private boolean _val = false;
    private final PropertyChangeSupport _changesupport = new PropertyChangeSupport(this);
}

This is a common pattern in Swing, and you can use PropertyChangeSupport to simplify the creation of objects on which you can observe and listen for property changes. With such classes, you can register a PropertyChangeListener to handle the resulting PropertyChangeEvents that result.

Michael Aaron Safyan
Nice with the `PropertyChangeSupport`. Why isn't it located in a more "generic" package?
aioobe
+1 for PropertyChangeSupport. Though I would just make it final and public and skip the add and remove methods on the Bool class.
Yar