views:

295

answers:

1

I'm in the midst of porting a C# program over to Java that makes heavy use of delegates and the delegate's BeginInvoke method to notify of an event asynchronously. Take a data communication thread for example. It might have to notify another worker thread of its state as well as the GUI.

It seems to me that the best way to notify of the various events for different classes is to have an IClassNameHereWatcher interface that defines all of the types of events that the class "publishing" the event would need to notify about and then each class that needs to listen would implement this interface and register itself as a listener. The thing I'm not quite sure about is how to make this asynchronous. Here's approximately what I'm referring to:

public interface IFrobWatcher {
    void frobDidSomething();
    void frobReceivedData(object data);
}

public class Frob implements Runnable {
    List<IFrobWatcher> watchers = new ArrayList<IFrobWatcher>();

    private void run() {
        while (true) {
            // Long running task
            if (blah) notifyWeDidSomething();
            notifyOfData(someDataObject);
        }
    }

    public void addWatcher(IFrobWatcher watcher) {
        watchers.Add(watcher);
    }

    private void notifyWeDidSomething() {
        for (IFrobWatcher watcher : watchers) {
            watcher.frobDidSomething(); // How do I make this asynchronous?
        }
    }

    private void notifyOfData(object someDataObject) {
        for (IFrobWatcher watcher : watchers) {
            watcher.frobReceivedData(someDataObject); // How do I make this asynchronous?
        }
    }

}

public class FrobWatcher implements IFrobWatcher {
    private Frob frobToWatch;

    public FrobWatcher(Frob frob) {
        frobToWatch = frob;
        frobToWatch.addListener(this);
    }

    public void FrobDidSomething() {
        System.out.println("Frob did something!");
    }

    public void FrobReceivedData(object received) {
        System.out.println("Frob received: " + received.ToString());
    }

    public static void main(string[] args) {
        Frob f = new Frob();
        FrobWatcher fw = new FrobWatcher(f);
        (new Thread(f)).start();
    }
}

And this is a fairly simplified example, but hopefully it conveys what I'm looking for. If something isn't clear or doesn't make sense, please comment and I'll try to clarify or fix the example.

+2  A: 

I would recommend an Executor from the java.util.concurrent package. This is how asynchronous callbacks are handled in the Raptor framework:

scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(
    filesPoller, 0 /*initial delay*/,
    checkInterval,
    TimeUnit.MILLISECONDS
);

NB. this scheduling is recurring.

Schildmeijer
It looks like the Executor framework might work! If I call `newSingleThreadExecutor()` and then call `execute` on something that calls `notifyWeDidSomething`, the event notification would be asynchronous, right?
jasonh
yes, thats right
Schildmeijer