Using the Observer and Observable Class
-
I am writing a small data driven application which takes data from an input and throw an event throughout the program that is subscribed to the data event listener. Currently, I have the small test program setup as an infinite loop to see if there are any memory leaks. Testing has shown that there is a massive memory leak and I don't know what to do. I have the program attached: What is happening is when the event is handled, it is not properly disposed of. Instead, it is thrown onto the stack while a new event is serviced. I thought sleeping the current event would dispose of the last event but...nope! I am out of ideas on how to properly service and dispose of events quickly using this form. Any ideas would be helpful to figure this small technical issue out. Thanks - Ryan The Main loop which has the data items and the main value observer.
import java.util.*;
public class CMain {
private final static int TIMEOUT = 250; // Public data...Could be in the form of a singleton. private static CValue Value; private static CData AddFive; private static CData AddTwo; private static CData AddTen; private static CData AddSeven; private static CData MaxValueReached; public static void main(String\[\] args) { // All the data variables which will be used Value = new CValue(); AddFive = new CData(); AddFive.setItsAction(new CAction() { @Override public void doAction() throws InterruptedException { Thread.sleep(TIMEOUT); if (Value.getItsValue() <= 20) { Value.setItsValue(Value.getItsValue() + 5); } } }); Value.addObserver(AddFive); AddTwo = new CData(); AddTwo.setItsAction(new CAction() { public void doAction() throws InterruptedException{ Thread.sleep(TIMEOUT); if (Value.getItsValue() > 20 && Value.getItsValue() <= 40) { Value.setItsValue(Value.getItsValue() + 2); } } }); Value.addObserver(AddTwo); AddTen = new CData(); AddTen.setItsAction(new CAction(){ public void doAction() throws InterruptedException{ Thread.sleep(TIMEOUT); if (Value.getItsValue() > 40 && Value.getItsValue() <= 80) { Value.setItsValue(Value.getItsValue() + 10); } } }); Value.addObserver(AddTen); AddSeven = new CData(); AddSeven.setItsAction(new CAction(){ public void doAction() throws InterruptedException{ Thread.sleep(TIMEOUT); if (Value.getItsValue() > 80) { Value.setItsValue(Value.getItsValue(
-
I am writing a small data driven application which takes data from an input and throw an event throughout the program that is subscribed to the data event listener. Currently, I have the small test program setup as an infinite loop to see if there are any memory leaks. Testing has shown that there is a massive memory leak and I don't know what to do. I have the program attached: What is happening is when the event is handled, it is not properly disposed of. Instead, it is thrown onto the stack while a new event is serviced. I thought sleeping the current event would dispose of the last event but...nope! I am out of ideas on how to properly service and dispose of events quickly using this form. Any ideas would be helpful to figure this small technical issue out. Thanks - Ryan The Main loop which has the data items and the main value observer.
import java.util.*;
public class CMain {
private final static int TIMEOUT = 250; // Public data...Could be in the form of a singleton. private static CValue Value; private static CData AddFive; private static CData AddTwo; private static CData AddTen; private static CData AddSeven; private static CData MaxValueReached; public static void main(String\[\] args) { // All the data variables which will be used Value = new CValue(); AddFive = new CData(); AddFive.setItsAction(new CAction() { @Override public void doAction() throws InterruptedException { Thread.sleep(TIMEOUT); if (Value.getItsValue() <= 20) { Value.setItsValue(Value.getItsValue() + 5); } } }); Value.addObserver(AddFive); AddTwo = new CData(); AddTwo.setItsAction(new CAction() { public void doAction() throws InterruptedException{ Thread.sleep(TIMEOUT); if (Value.getItsValue() > 20 && Value.getItsValue() <= 40) { Value.setItsValue(Value.getItsValue() + 2); } } }); Value.addObserver(AddTwo); AddTen = new CData(); AddTen.setItsAction(new CAction(){ public void doAction() throws InterruptedException{ Thread.sleep(TIMEOUT); if (Value.getItsValue() > 40 && Value.getItsValue() <= 80) { Value.setItsValue(Value.getItsValue() + 10); } } }); Value.addObserver(AddTen); AddSeven = new CData(); AddSeven.setItsAction(new CAction(){ public void doAction() throws InterruptedException{ Thread.sleep(TIMEOUT); if (Value.getItsValue() > 80) { Value.setItsValue(Value.getItsValue(
I think you failed to understand the publisher-subscriber framework. Publisher has many subscriber .i.e one to many relation ship with subscriber.Publisher post the new event(if any), and all the subscriber which have the subscription, will catch the event. So this is pretty much concept. In java , publisher as Observable and subscriber as Observer. Now, in your app you create an Observable (CValue). Then you create Observer which is again an Observable(CData extends Observable) and register this with the Observable, means you register an Observable with another Observable. So fixed this things before moving forward
Regards Shubhashish
-
I think you failed to understand the publisher-subscriber framework. Publisher has many subscriber .i.e one to many relation ship with subscriber.Publisher post the new event(if any), and all the subscriber which have the subscription, will catch the event. So this is pretty much concept. In java , publisher as Observable and subscriber as Observer. Now, in your app you create an Observable (CValue). Then you create Observer which is again an Observable(CData extends Observable) and register this with the Observable, means you register an Observable with another Observable. So fixed this things before moving forward
Regards Shubhashish
Shubhashish, thank you for taking the time to analyze and reply to my original message. I am learning new concepts in Java to become a better programmer. I have taken you comments into serious consideration and updated the code. The class headers for CValue and CData are as follows:
public class CValue extends Observable
public class CData implements ObserverI would execute the test program for a minute to two minutes before its crashes out. What I am observing during execution is this: CMain.doAction() CValue.setItsValue(double) CValue.notifyObservers() CData.update(Observerable,Object) CMain.doAction ... Repeat until thread crash It seems the events are not being closed completely after the servicing of the observer. I know I am creating a lot of events being generated quickly but isn't there a mechanism which would close these events or am I not closing them down properly myself? Ryan
-
Shubhashish, thank you for taking the time to analyze and reply to my original message. I am learning new concepts in Java to become a better programmer. I have taken you comments into serious consideration and updated the code. The class headers for CValue and CData are as follows:
public class CValue extends Observable
public class CData implements ObserverI would execute the test program for a minute to two minutes before its crashes out. What I am observing during execution is this: CMain.doAction() CValue.setItsValue(double) CValue.notifyObservers() CData.update(Observerable,Object) CMain.doAction ... Repeat until thread crash It seems the events are not being closed completely after the servicing of the observer. I know I am creating a lot of events being generated quickly but isn't there a mechanism which would close these events or am I not closing them down properly myself? Ryan
Please update the code with your changes. May be there are some memory leak. This may help you http://www.java2s.com/Code/Java/Design-Pattern/AsimpledemoofObservableandObserver.htm[^]
Regards Shubhashish
-
Please update the code with your changes. May be there are some memory leak. This may help you http://www.java2s.com/Code/Java/Design-Pattern/AsimpledemoofObservableandObserver.htm[^]
Regards Shubhashish
I have been using java2s for all my questions on this problem. Updated Code: (Use the original posted code for classes not posted here)
public class CData implements Observer
{
public CData()
{
// Do Nothing
}
@Override
public void update(Observable arg0, Object arg1) {
if (itsAction != null)
{
try {
this.itsAction.doAction();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}private CAction itsAction = null; public CAction getItsAction() { return itsAction; } public void setItsAction(CAction itsAction) { this.itsAction = itsAction; }
}
public class CValue extends Observable
{
private double itsValue = 0;public double getItsValue() { return itsValue; } public void setItsValue(double itsValue) { if (this.itsValue != itsValue) { this.itsValue = itsValue; System.out.print("Value set to " + itsValue + "\\n"); setChanged(); notifyObservers(); } } public void startBehavior() { setChanged(); notifyObservers(); } }
Observation: When I execute setChanged and then execute notifyObservers, the test program does a re-calculation on the new data. If the re-calculation doesn't change the value, then no new notifications are required. If there is a change in data from the re-calculation then the process is started all over again. I made a small modification to CMain to stop the notifications after a period of time and restart the re-calculation process again. This is eliminating the memory leak completely. From these new revelations, attached is my new CMain code
public class CMain {
private final static int TIMEOUT = 5; // Public data...Could be in the form of a singleton. private static CValue Value; private static CData AddFive; private static CData AddTwo; private static CData AddTen; private static CData AddSeven; private static CData MaxValueReached; public static void main(String\[\] args) { // All the data variables which will be used Value = new CValue(); AddFive = new CData(); AddFive.setItsAction(new CAction() { @Override public void doAction() throws InterruptedException { Thread.sleep(TIMEOUT); if (Value.getItsValue() <= 20) { Value.setItsValue(Value.getItsValue() + 5); } } }); Value.addObserver(AddFive); AddTwo = new CData(); AddTwo.setItsAction(new CActi
-
I have been using java2s for all my questions on this problem. Updated Code: (Use the original posted code for classes not posted here)
public class CData implements Observer
{
public CData()
{
// Do Nothing
}
@Override
public void update(Observable arg0, Object arg1) {
if (itsAction != null)
{
try {
this.itsAction.doAction();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}private CAction itsAction = null; public CAction getItsAction() { return itsAction; } public void setItsAction(CAction itsAction) { this.itsAction = itsAction; }
}
public class CValue extends Observable
{
private double itsValue = 0;public double getItsValue() { return itsValue; } public void setItsValue(double itsValue) { if (this.itsValue != itsValue) { this.itsValue = itsValue; System.out.print("Value set to " + itsValue + "\\n"); setChanged(); notifyObservers(); } } public void startBehavior() { setChanged(); notifyObservers(); } }
Observation: When I execute setChanged and then execute notifyObservers, the test program does a re-calculation on the new data. If the re-calculation doesn't change the value, then no new notifications are required. If there is a change in data from the re-calculation then the process is started all over again. I made a small modification to CMain to stop the notifications after a period of time and restart the re-calculation process again. This is eliminating the memory leak completely. From these new revelations, attached is my new CMain code
public class CMain {
private final static int TIMEOUT = 5; // Public data...Could be in the form of a singleton. private static CValue Value; private static CData AddFive; private static CData AddTwo; private static CData AddTen; private static CData AddSeven; private static CData MaxValueReached; public static void main(String\[\] args) { // All the data variables which will be used Value = new CValue(); AddFive = new CData(); AddFive.setItsAction(new CAction() { @Override public void doAction() throws InterruptedException { Thread.sleep(TIMEOUT); if (Value.getItsValue() <= 20) { Value.setItsValue(Value.getItsValue() + 5); } } }); Value.addObserver(AddFive); AddTwo = new CData(); AddTwo.setItsAction(new CActi
few things that you have to know. Role of the Observer is to notify each subscriber if any changes happen. If you see in your code there is a recursive call exist. In your main class , at the end, you are setting value in Observer. So Observer value changed and it convey the notify message to the subscriber.Again If you see in doAction() ,you can see that each Subscriber receive the notify message and again set the Observer value with new one. There for this action again update the Observer value and again Observer doing the above thing and thus fall in recursive call.
Regards Shubhashish
-
few things that you have to know. Role of the Observer is to notify each subscriber if any changes happen. If you see in your code there is a recursive call exist. In your main class , at the end, you are setting value in Observer. So Observer value changed and it convey the notify message to the subscriber.Again If you see in doAction() ,you can see that each Subscriber receive the notify message and again set the Observer value with new one. There for this action again update the Observer value and again Observer doing the above thing and thus fall in recursive call.
Regards Shubhashish
Where "Observer" is actually "Observable" as you got it right in your first post, since "Observer" and "Subscriber" are basically the same thing.