I have the following interfaces:
public interface NumberOfCellsListener {
public void numberOfCellsChanged(int patientId, int numOfCells);
}
public interface NumberOfCells {
public void register(NumberOfCellsListener listener);
public int numOfCells(int patientId);
}
public interface ProbabilityOfCancer {
//this may be a time consuming calculation
public double probability(int patientId, int numOfCells, bool gender, double weight);
}
This is the structure of my cancer probability calculator. My task is to implement this such that it can be called asynchronously due to the time consuming nature of the calculations. I am new to Java, can anyone please guide me on how to implement these interfaces? I am not sure about the structure i.e. what goes where. I am guessing I should get the new number of cells from the method numberOfCellsChanged in NumberOfCellsListener's implementation. But since it is a void method, I am not sure what to do.
An Interface method that does not return something usually has the function of changing the internal state, or of using some other means of output (for example to print something to the console, send something over a network, or save it to a database or file.).
As for the specific interfaces:
A Listener as in NumberOfCellsListener is meant to be installed ('registered') with an object that calls a listener's method, in case a specific event occures. In your case, based on the interface name, I would assume, that your method is called, when the number of cells of some object changes. So the question for you should be, what that information (at that point) requires you to do, and do that in the method.
A class implementing NumberOfCells is supposed to make true of the above statement. It has a register method, that should put the listener in some sort of collection (maybe a List - e.g. an ArrayList?) and then, when a certain event occures, invoke all the list's listener's numberOfCellsChanged-methods.
So an example implementation could be:
public class NumberOfCellsPrinter implements NumberOfCellsListener {
public void numberOfCellsChanged(int patientId, int numOfCells) {
System.out.println("The number of cells for parentId:" + parentId + " has changed to " + numOfCells + ".");
}
}
...
public class PetriDish implements NumberOfCells {
private ArrayList<NumberOfCellsListener> listeners = new ArrayList<>();
private int numOfCells = 0;
public void register(NumberOfCellsListener listener) {
if (listener != null && !listeners.contains(listener)) {
listeners.add(listener);
}
}
public int numOfCells(int patientId) {
for (NumberOfCellsListener listener : listeners) {
listener.numberOfCellsChanged(parentId, numOfCells);
}
return numOfCells;
}
}
While this example is totally meaningless, and will always produce 0 as numOfCells, it should demonstrate the idea of listeners.
It is very important, that you familiarize yourself with the risks and traps concerning parallelism, since this is a key factor of your objective.
Try the following to learn about async callbacks in Java. You can find more tutorials and explanations here
// Java program to illustrate Asynchronous callback
interface OnGeekEventListener {
// this can be any type of method
void onGeekEvent();
}
class B {
private OnGeekEventListener mListener; // listener field
// setting the listener
public void registerOnGeekEventListener(OnGeekEventListener mListener)
{
this.mListener = mListener;
}
// My Asynchronous task
public void doGeekStuff()
{
// An Async task always executes in new thread
new Thread(new Runnable() {
public void run()
{
// perform any operation
System.out.println("Performing operation in Asynchronous Task");
// check if listener is registered.
if (mListener != null) {
// invoke the callback method of class A
mListener.onGeekEvent();
}
}
}).start();
}
// Driver Program
public static void main(String[] args)
{
B obj = new B();
OnGeekEventListener mListener = new A();
obj.registerOnGeekEventListener(mListener);
obj.doGeekStuff();
}
}
class A implements OnGeekEventListener {
#Override
public void onGeekEvent()
{
System.out.println("Performing callback after Asynchronous Task");
// perform some routine operation
}
// some class A methods
}
Related
I am trying to implement an Annotation based Event System for my OpenGL Game Engine. I apply the #EventListener Annotation on the method which I want to be called like this:
#EventListener(type = Type.COLLISION)
public void OnCollision(CollisionEvent data)
{
System.out.println("HI");
}
The class in which this method sits implements an Empty Interface:
public class Sprite implements EventHandler
The EventDispatcher class:
public class EventDispatcher
{
private static List<EventHandler> registered = new ArrayList<EventHandler>();
public static void register(EventHandler EventHandler)
{
if (!registered.contains(EventHandler))
{
registered.add(EventHandler);
}
}
public static void unregister(EventHandler EventHandler)
{
if (registered.contains(EventHandler))
{
registered.remove(EventHandler);
}
}
public static List<EventHandler> getRegistered()
{
return registered;
}
public static void dispatch(final Event event)
{
new Thread()
{
#Override
public void run()
{
call(event);
}
}.start();
}
private static void call(final Event event)
{
for (EventHandler registered : getRegistered())
{
Method[] methods = registered.getClass().getMethods();
for (int i = 0; i < methods.length; i++)
{
System.out.println("Annotation Being Checked");
if (methods[i].isAnnotationPresent(EventListener.class))
{
System.out.println("Has Annotation");
Class<?>[] methodParams = methods[i].getParameterTypes();
if (methodParams.length < 1)
{
continue;
}
if (!event.getClass().getSimpleName().equals(methodParams[0].getSimpleName()))
{
continue;
}
try
{
methods[i].invoke(registered.getClass().newInstance(), event);
} catch (Exception exception)
{
System.err.println(exception);
}
} else System.out.println("No Annotation");
}
}
}
}
But when I run the program, It always prints out
Annotation Being Checked
No Annotation
multiple Times.
Can someone help? If more information is needed, please ask and I will edit the Question.
I setup a project based on your example and it's working fine. You will however see some "No Annotation" messages as your code evaluates all methods of the Sprite event handler. Even if you don't implement any additional methods other than OnCollision each class will inherit default methods from Object such as equals, hashCode or toString.
Test class:
public class SpriteTest {
public static void main(String[] args) {
EventDispatcher.register(new Sprite());
CollisionEvent collisionEvent = new CollisionEvent();
EventDispatcher.dispatch(collisionEvent);
}
}
Apart from that there are some obvious flaws in your code:
Don't use stateful static members (EventDispatcher.registered) unless you know what you're doing and are aware of the multithreading aspects that come with it
You store instances of EventHandler but only use the class information and create a new instance on the fly - why not register the class instead of an instance directly
You fork new Threads for each to be dispatched event. This is very bad practice as thread creation is a costly operation. Use a thread pool instead and submit runnables or callables
You check if the class' simple names match to see if a handler method is applicable. This will break when using inheritance and should be replaced by Class.isAssignableFrom
In general usage of annotations here is questionable. You're probably better off using dedicated interfaces for the different event types. Instead of a generic EventHandler there could be a CollisionEventHandler and so on...
Rough implementation idea
public interface CollisionEventHandler extends EventHandler {
void onCollision(CollisionEvent event);
}
public class Sprite implements CollisionEventHandler {
public void onCollision(CollisionEvent data) {
System.out.println("HI");
}
}
public class EventDispatcher {
...
static void call(final CollisionEvent event) {
getRegistered().stream()
.filter(handler -> handler instanceof CollisionEventHandler)
.map(handler -> (CollisionEventHandler) handler)
.forEach(handler -> handler.onCollision(event));
}
}
To handle different types of events you will need different call/dispatch methods. Maybe you can use the Visitor pattern (though I'm not a fan of it).
This question may be duplicated because I found a lot of similar question, but not the answer to my problem: I need to update the view of my SWING application from different SwingWorker.
I have a View class with a JTextArea and a JTable that i need to update during the execution of the Threads. The view also has a Start button that launch all the threads.
The controller listens for the button to be clicked then launch the threads:
public class MonitorPageController {
private MonitorPage monitorPage;
private List<Mission> missions;
class StartButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < missions.size(); i++) {
MyWorker worker = new MyWorker(missions.get(i));
worker.execute();
}
}
}
}
Then I have MyWorker class that manage the model:
public class MyWorker extends SwingWorker<Integer, String> {
private Mission m;
//<dec>
Block block1 = new Block();
Block block2 = new block();
Block block3 = new Block();
Block block4 = new Block();
public MyWorker(Mission mission) {
this.m = mission;
}
#Override
protected Integer doInBackground() throws Exception {
//<exe>
block1.addObserver(block2);
block2.addObserver(block3);
block3.addObserver(block4);
block4.addObserver(block2);
block1.update(null, m);
return 4;
}
}
In the end I have the Block class that is where I need to update the GUI (JTable and JTextArea):
public class Block extends Node implements Observer {
public Mission run(Mission m) {
m.setStatus(Mission.UNEXECUTED);
// HERE I WANT TO NOTIGY THE VIEW OF THE CHANGE OF STATUS OF THE MISSION
return m;
}
#Override
public void update(Observable o, Object arg) {
Mission m = this.run((Mission) arg);
setChanged();
notifyObservers(m);
}
}
EDIT: Mission is a simple class with the attribute: int status
I already tried with another observer pattern: I setted the mission as observable and the MonitorPageController as the observer. Then in the setter method of the status in class Mission I added the setChanged() and the notifyObservers() methods. In the end in the Observer (MonitoPageController) I implemented the update() method to call the view and update the gui.
I liked this way because it's clean and easy to implement, but I don't now why, after calling the notifyObserver() nothing was happening, so I discarded this solution, even if it seems to be the right one
Update the UI calling SwingUtilities.invokeLater() :
public class Block extends Node implements Observer {
public Mission run(Mission m) {
m.setStatus(Mission.UNEXECUTED);
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
//UPDATE UI HERE
}
});
return m;
}
#Override
public void update(Observable o, Object arg) {
Mission m = this.run((Mission) arg);
setChanged();
notifyObservers(m);
}
}
I found a possible solution, maybe there better ideas, but this works for now:
Creating the SwingWorker in MonitorPageController I changed the constructor passing the istance of the MonitorPageController too.
MyWorker worker = new MyWorker(misssions.get(i), this);
Then in MyWorker class when I create Block1, Block2, ...I pass them the istance of the MyWorker:
Block block1 = new Block(this);
Block block2 = new Block(this);
....
In the same class (MyWorker) I created a method:
public void log(Mission m, String s) {
controller.log(m, s);
}
Controller is the istance of the MonitorPageController that created the worker.
Now the inside block class, when I want to notify the change of status, I can call:
parentWorker.log(mission, "some string");
In the end the log() method in the MonitorPageController calls the view method to update the components...by now it seems to work...
The below method onReceivedTitlegets called 2-3 times with in a second when webview url changes. I want to call a method in it, when onReceivedTitle is being called last time. I am doing this because I just want to monitor url changes with in webview. shouldOverrideUrlLoading is not getting called when url changes through ajax.
class MyWebChromeClient extends WebChromeClient {
#Override
public void onReceivedTitle(WebView view, String title) {
Log.v("onReceivedTitle", "=>" + title);
// callAMehod();
super.onReceivedTitle(view, title);
}
}
If you want to throttle how often a method call causes another method call you can do so for example via a Handler. The simplest version enqueues a delayed message on the first call and any subsequent call while there is an enqueued message will not enqueue a new one. That results in 1 call every X time to go though - but it take at least that amount of time until the first action happens.
Example implementation (you can put that class unmodified somewhere in your code)
public abstract class ThrottleExecutor {
private final long mMinDelay;
public ThrottleExecutor(long minDelay) {
mMinDelay = minDelay;
}
/** Implement to do something */
public abstract void doThrottled();
public final void scheduleExecution() {
if (mHandler.hasMessages(0)) {
// message already enqueued, do nothing
} else {
// otherwise enqueue a message for later
mHandler.sendEmptyMessageDelayed(0, mMinDelay);
}
}
public final void cancelExecution() {
mHandler.removeMessages(0);
}
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(Message msg) {
doThrottled();
}
};
}
And then use it for example like so
class Usage {
private ThrottleExecutor mThrottle = new ThrottleExecutor(2000) {
#Override
public void doThrottled() {
// happens at most every 2000ms
methodToBeThrottled();
}
};
void methodThatHappensTooOften() {
mThrottle.scheduleExecution();
}
void methodToBeThrottled() {
Log.d("TAG", "triggered at 2000ms before");
}
}
You might want to use Handler and do something like this:
class MyWebChromeClient extends WebChromeClient {
private boolean mOnReceivedTitleInvoked;
#Override
public synchronized void onReceivedTitle(final WebView view, final String title) {
if (!mOnReceivedTitleInvoked) {
mOnReceivedTitleInvoked = true;
Log.v("onReceivedTitle", "=>" + title);
handler.postDelayed(new Runnable() {
#Override
public void run() {
super.onReceivedTitle(view, title);
mOnReceivedTitleInvoked = false;
}
}, 1000);
}
}
}
Although you might want to reconsider the onReceivedTitle behaviour.
I'm having a really bad time to implement a listener to a method.
In my current work i have to request a method every 5 seconds in order to verify for new information so i want to implement a method to notify me every time a new information come discarding the requesting method in every 5 seconds.
(I already read about observer pattern but had no successful in implementing.)
best regards
More information:
For now i m overriding this method from the smack XMPP library in order to store new messages in msgs Queue
public void processMessage(Chat chat, Message message) {
if (message.getType() == Message.Type.chat) {
req = message.getBody().toString();
String[] temp = { chat.getParticipant().toString(), req };
System.out.println(temp[0]+"says:"+temp[1]);
synchronized (lock) {
msgs.add(temp);
}
}
}
and than i have this method executed every 0.5 seconds in order to verify new messages:
public String[] getMessage() {
synchronized (lock) {
String[] data;
data=msgs.poll();
return data;
}
}
i'm trying to set a notification system that notifies me everytime the processMessage is executed.
Ok i manage to solve my problem.
I implemented a listener based on observer model. For that i had to implement a interface that i called XMPPmessageListener:
public interface XMPPmessageListener {
public void readMsg(String senderJID, String msg);
}
than in the XmppHandler class, the class of the methods processMessage and getMessage i added methods to add and remove listeners and a LinkedList to store the listeners:
private LinkedList<XMPPmessageListener> listeners = new LinkedList<XMPPmessageListener>();
public void addMsgListener(XMPPmessageListener listener){
listeners.add(listener);
}
public boolean removeMsgListener(XMPPmessageListener listener){
return listeners.remove(listener);
}
than i did some exchanges in processMessage method in order to warn the listeners:
public void processMessage(Chat chat, Message message) {
if (message.getType() == Message.Type.chat) {
for(XMPPmessageListener l: listeners){
l.readMsg(chat.getParticipant().toString(), message.getBody().toString());
}
}
}
Now i can be notified at any method everytime a message is receive by creating a XMPPmessageListener and decide what to do with the message by overriding the readMsg method:
XmppHandler xmpp = new XmppHandler(XMPPuser, XMPPpassword, XMPPaddress, XMPPdomain, XMPPport);
XMPPmessageListener msglistener = new XMPPmessageListener() {
#Override
public void readMsg(String senderJID, String msg) {
String asw=xmlHandler.processMsg(msg,senderJID);
}
};
xmpp.addMsgListener(msglistener);
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.
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.