I have a Singleton class to save the state of an application's module.
This class simply have a lot of class variables with setters and getters :
public class ModuleState{
private static ModuleState instance;
private A a;
private B b;
private C c;
..
..
..
..
private ModuleState (){}
public ModuleState getInstance(){
if(instance==null)
instance=new ModuleState();
return instance;
}
}
At a precise moment of the application lifecycle, i have the need to CLEAR the module's state. What i do now is to reset ALL the variables in ModuleState by a clearAll() method like this:
public void clearAll(){
a=null;
b=null;
c=null;
..
..
}
My question is the following : there is a cleaner method to do this reset? Possibly clearing the singleton instance itself, without resetting every class variable?
The problem with this approach is that i may have the need to add a new class variable to the ModuleState. In this case i must remember to add a line in the clearAll() method to reset the new variable.
What about ...
public static volatile ModuleState instance = null;
public static void reset() {
instance = new ModuleState();
}
p.s.: as per discussion below: in a multithreaded environment it's very important to synchronize the access on the instance because the JVM is allowed to cache its value. You can use volatile as shown above. Thanks to all!
Cheers!
no, this approach is perfectly acceptable. you are of course synchronizing access to these state objects in some way, right? otherwise you risk someone seeing a half-cleared config object.
another thing you could do to future-proof yourself against any extra state added in the future is store all of your state in a HashMap, for example, instead of individual fields. this way, clear()ing the hashmap ensures that all state is wiped and adding any extra state in the future becomes safer
You need to maintain the same object instance, in order to comply with the Singleton pattern, so your approach makes sense: altering the members.
However, if you wanted to clean it up a little bit, why not just have an internal list, like:
ArrayList<Object> members = new ArrayList<Object>();
// If it actually is Object, there's no need to paramaterize.
// If you want, you can actually make the members implement a common interface,
// and parameterize the ArrayList to that.
Another Option would be to have a HashMap, that binds the key word to the member.
HashMap<String,Object> members = new HashMap<String,Object>();
// Again, same parameterization rules apply.
For an ArrayList or a HashMap, the clearAll method might look like this:
public class ModuleState()
{
public void clearAll()
{
members.clear();
}
}
This method won't need to change.
May be this can help you:
public class SingletonBean {
private static SingletonBean instance = new SingletonBean();
private static Object privateMutex = new Object();
private SingletonBean() {
//to prevent instantiation
}
public class ObjectsContainer {
private Object A;
private Object B;
private Object C;
public Object getA() {
return A;
}
public void setA(Object a) {
A = a;
}
public Object getB() {
return B;
}
public void setB(Object b) {
B = b;
}
public Object getC() {
return C;
}
public void setC(Object c) {
C = c;
}
}
private ObjectsContainer objectsContainer;
private void resetObjectsContainer() {
objectsContainer = new ObjectsContainer();
}
public static SingletonBean getInstance() {
return SingletonBean.instance;
}
public static void clearAll() {
synchronized (privateMutex) {
SingletonBean.getInstance().resetObjectsContainer();
}
}
public static ObjectsContainer getObjectsContainer() {
synchronized (privateMutex) {
return instance.objectsContainer;
}
}
}
public class SomeClass {
public void someMethod() {
SingletonBean.getObjectsContainer().getA();
}
}
Make an inner class to hold the fields, then replace that instance when you want to reset. The write to the field would make the change to all three fields essentially atomic.
public class ModuleState {
private static volatile ModuleState instance;
private static class Values {
A a;
B b;
C c;
}
private volatile Values values = new Values()(
private ModuleState (){}
public ModuleState getInstance(){
if (instance==null) {
synchronized (ModuleState.class) {
if (instance==null) {
instance = new ModuleState();
}
}
}
return instance;
}
public synchronized A getA() {
return values.a;
}
public synchronized void reset() {
values = new Values();
}
By the way, your null checking initialization code was not threadsafe. I fixed that too.
Note that to make this work, you must make the reference to values volatile and synchronize all access to it, otherwise (due to the java memory model) other threads than the one that calls reset() may see the old reference.
Related
When one object of a class has a reference to another object of
the same class, the first object can access all the second object’s
data and methods (including those that are private).
I took this sentence from a book. But I couldn't figure out actually what it means.
It means that private members are visible to other instances of the same class. For example:
class A {
private int v;
public boolean isSameV(A other) {
return this.v == other.v; // can acccess other.v
}
}
It means that if you have a class that looks like this
public class A {
private int number;
private A otherInstance;
public int number2;
public void DoStuff() {
...
}
}
you can access A.number in the DoStuff method (or any other class method) even although number is actually private.
e.g.
public class A {
...
public void DoStuff() {
this.otherInstance.number = 42;
^^^^^^^
cannot access private members here
}
}
is perfectly fine, while
public class B {
private A aInstance;
public void DoStuffToo() {
this.aInstance.number = 42;
}
}
would not compile, because B cannot access A's private members.
Good question actually, I faced similar problem when I started learning Java, here is how it looks in practice:
public class A {
private String example;
protected int anotherOne;
public A(){
}
public A(A a){
this.example = a.example; // here we get access to private member of another object of same class
this.anotherOne = a.anotherOne; // it works for protected as well
}
// This works for methods not just constructor, lets consider we want to swap value of example:
public void swapExample(A a){
String temp = a.example;
a.example = this.example;
this.example = temp;
}
}
Private fields can be accessed from inside of the class, by this construction you can access all the field of an instance of Foo without getters and setters when you are in class Foo :
public class Foo {
private String name;
public int sumLetter(Foo b) {
return this.name.length() + b.name.length();
}
}
The doc : Declaring Member Variables :
private modifier — the field is accessible only within its own class.
I need a way to check if a boolean value of another object is true, and only in that case should do something.
So, I have 2 classes:
public class A{
private boolean test = false;
...
...
public boolean returnTest(){ return test; }
}
public class B{
private boolean abcd;
public B(A myA){
this.abcd = myA.returnTest();
}
public void test(){
while(!abcd){
// wait
}
// do something
}
}
The problem is that it remain in the while loop forever even if the test value of the object A become true. Why ?
In your case, pass instance to function test() is better, invoke test() with passing instance of A. Everytime an new instance of A is created or an existing instance has updated its attributes, pass it to test()
public void test(A a){
while(!a.returnTest()){
// wait
}
}
There is no real alternative to changing test() to do while (!myA.returnTest()). If you store a result in a variable it will stay permanently. (Properties of objects, or method calls, can reflect changes elsewhere, but variables themselves cannot.)
Booleans are immutable so you cannot make a copy of a reference to them.
Instead, try:
public class B{
private A a;
public B(A myA){
this.a= myA();
}
public void test(){
while(!myA.returnTest()){
// wait
}
// do something
}
}
In Java 8 you can use a method reference.
public class A{
private boolean test = false;
...
...
public boolean returnTest(){ return test; }
}
public class B{
private BooleanSupplier abcd;
public B(A myA){
this.abcd = myA::returnTest; // a reference to this method.
}
public void test(){
while(!abcd.getAsBoolean()) { // calls the method each time.
// wait
}
// do something
}
}
If you must do so, one option is to use a java.util.concurrent.atomic.AtomicBoolean, which is mutable type. You can retrieve and update values using get() and set(boolean) respectively. This can also be a good option if thread-safety can potentially be a concern in your application.
Otherwise you have to store a reference to the A instance and use the flag inside it instead of checking a different variable.
Can someone give me an example of when you'd use a private static field over a private static final field? I struggle to think of an example of when you'd want to declare a private class variable, that was subject to change.
Enter the Singleton pattern:
public class Clazz {
public static void main(String[] args) {
MyObject myObject = MyObject.getInstance();
}
}
class MyObject {
private static MyObject instance;
//I belong to the class, but I need not be created before somebody wants me.
private MyObject() {
}
public static MyObject getInstance() {
if (instance == null) {
instance = new MyObject();
}
return instance;
}
}
Yes.
For example when you want to have a counter variable to count how many objects have been created from a class, you'll make it static - it's associated with the class and not an object, but it's not final since it's changing:
protected static int counter = 0;
//constructor
counter++;
Worth mentioning note:
I didn't mention the Singleton example since if you want to be thread-safe, the variable must be static and final.
here is my problem
class A{
private B b = new B(this); // line 2
A(){}
}
This is just an ex. code and works fine. But i have a doubt about this is used to current reference (instance of A). Class initializing happens before to get a class instance. So how can we put this in line 2. i asked does instantiation happen before initializing?
You bring up an interesting point. Here is a contrived instructional example that demonstrates a run time problem that can happen when using your example.
class A {
private boolean isInitialized = false;
private final B b = new B(this);
public A() {
initialize();
}
private void initialize() {
isInitialized = true;
}
public boolean isInitialize() {
return isInitialized;
}
public B getB() {
return b;
}
}
class B {
private boolean isInitialized = false;
final private A a;
public B(final A a) {
this.a = a;
initialize();
System.out.println("inB: a.isInitialize()=" + a.isInitialize());
}
private void initialize() {
isInitialized = true;
}
public boolean isInitialize() {
return isInitialized;
}
}
public static void main(final String[] args) {
final A a = new A();
System.out.println("inMain: a.isInitialize()=" + a.isInitialize());
System.out.println("inMain:a.getB().isInitialize()=" + a.getB().isInitialize());
}
Output:
inB: a.isInitialize()=false
inMain: a.isInitialize()=true
inMain:a.getB().isInitialize()=true
Using the passed reference to class A within class B runs the real risk of using an object that is not fully initialized.
Be careful.
This is not class initialization (try to debug new ClassA() step by step), it is actually instance initialization.
There can be some problems if the constructor (from ClassB) calls some functions from ClassA, which access some fields in ClassA that are not initialized.
Edit: this is done before the constructor is called.
this is used correctly. The constructor doesn't need to be called at all.
No need for changes, everything is fine. this is a valid reference to A.
this will show its existence when you create an object of class A. Instance variable are assigned after object creation and static variable are initialize as soon as class loads and also before creations of any object.
you cannot use above initialization in static block
static {
private B b = new B(this); // compiler error. you cannot use 'this' in static context.
}
This is a question concerning what is the proper way to synchronize a shared object in java. One caveat is that the object that I want to share must be accessed from static methods. My question is, If I synchronize on a static field, does that lock the class the field belongs to similar to the way a synchronized static method would? Or, will this only lock the field itself?
In my specific example I am asking: Will calling PayloadService.getPayload() or PayloadService.setPayload() lock PayloadService.payload? Or will it lock the entire PayloadService class?
public class PayloadService extends Service {
private static PayloadDTO payload = new PayloadDTO();
public static void setPayload(PayloadDTO payload){
synchronized(PayloadService.payload){
PayloadService.payload = payload;
}
}
public static PayloadDTO getPayload() {
synchronized(PayloadService.payload){
return PayloadService.payload ;
}
}
...
Is this a correct/acceptable approach ?
In my example the PayloadService is a separate thread, updating the payload object at regular intervals - other threads need to call PayloadService.getPayload() at random intervals to get the latest data and I need to make sure that they don't lock the PayloadService from carrying out its timer task
Based on the responses, I refactored to the following:
public class PayloadHolder {
private static PayloadHolder holder;
private static PayloadDTO payload;
private PayloadHolder(){
}
public static synchronized PayloadHolder getInstance(){
if(holder == null){
holder = new PayloadHolder();
}
return holder;
}
public static synchronized void initPayload(){
PayloadHolder.payload = new PayloadDTO();
}
public static synchronized PayloadDTO getPayload() {
return payload;
}
public static synchronized void setPayload(PayloadDTO p) {
PayloadHolder.payload = p;
}
}
public class PayloadService extends Service {
private static PayloadHolder payloadHolder = PayloadHolder.getInstance();
public static void initPayload(){
PayloadHolder.initPayload();
}
public static void setPayload(PayloadDTO payload){
PayloadHolder.setPayload(payload);
}
public static PayloadDTO getPayload() {
return PayloadHolder.getPayload();
}
...
Is this approach legitimate? I am also curious if it is better to do it this way or using the AtomicReference approach mentioned by Hardcoded ...?
- I am keeping an instance of PayloadHolder on PayloadService simply to keep a reference to the PayloadHolder class active in the jvm for as long as the PayloadService is running.
Your code should look like this:
public static void setPayload(PayloadDTO payload){
synchronized(PayloadService.class){
PayloadService.payload = payload;
}
}
public static PayloadDTO getPayload() {
synchronized(PayloadService.class){
return PayloadService.payload ;
}
}
Your original code wouldn't have worked even if the methods weren't static. The reason being is you were synchronizing on the payload instance that you were changing.
Update, a response to johnrock comment:
Locking the whole class is only a problem if you have other synchronized static blocks that you want to run currently. If you want to have multiple independent locked section then I suggest you do something like this:
public static final Object myLock = new Object();
public static void setPayload(PayloadDTO payload){
synchronized(myLock){
PayloadService.payload = payload;
}
}
public static PayloadDTO getPayload() {
synchronized(myLock){
return PayloadService.payload ;
}
}
Or, if you require a more complex concurrency pattern look at java.util.concurrent which has many pre-built classes to aid you.
You could, as mentioned in other posts, synchronize on the class or on an explicit monitor.
There are 2 other ways, if we assume that your are using the sychnronize only for thread-safe getting and setting of the property: volatile and AtomicReference.
volatile
The volatile keyword will make access to the variable atomic, meaning that reading and assigning the variable won't be optimized by the CPUs local registers and are done atomically.
AtomicReference
The AtomicReference is a special class at the java.util.concurrent.atomic package, which allows atomic access to a variable-like reference. It is very similiar to volatile, but gives you some additional atomic operations, like compareAndSet.
Example:
public class PayloadService extends Service {
private static final AtomicReference<PayloadDTO> payload
= new AtomicReference<PayloadDTO>(new PayloadDTO());
public static void setPayload(PayloadDTO payload){
PayloadService.payload.set(payload);
}
public static PayloadDTO getPayload() {
return PayloadService.payload.get ;
}
Edit:
Your Holder seems quite confused, since you are instantiating classes only to call static Methods. A try to get it fixed with AtomicReference:
public class PayloadHolder {
private static AtomicReference<PayloadHolder> holder = new AtomicReference<PayloadHolder();
//This should be fetched through the holder instance, so no static
private AtomicReference<PayloadDTO> payload = new AtomicReference<PayloadDTO>();
private PayloadHolder(){
}
public static PayloadHolder getInstance(){
PayloadHolder instance = holder.get();
//Check if there's already an instance
if(instance == null){
//Try to set a new PayloadHolder - if no one set it already.
holder.compareAndSet(null, new PayloadHolder());
instance = holder.get();
}
return instance;
}
public void initPayload(){
payload.set(new PayloadDTO());
//Alternative to prevent a second init:
//payload.compareAndSet(null, new PayloadDTO());
}
public PayloadDTO getPayload() {
return payload.get;
}
public void setPayload(PayloadDTO p) {
payload.set(p);
}
}
public class PayloadService extends Service {
private final PayloadHolder payloadHolder = PayloadHolder.getInstance();
public void initPayload(){
payloadHolder.initPayload();
}
public void setPayload(PayloadDTO payload){
payloadHolder.setPayload(payload);
}
public PayloadDTO getPayload() {
return payloadHolder.getPayload();
}
}
My question is, If I synchronize on a static field, does that lock the class the field belongs to similar to the way a synchronized static method would? Or, will this only lock the field itself?
No, it just lock in the object itself ( the class attribute not the whole class )
Is this a correct/acceptable approach ?
You could probably take a look at the java.util.concurrent.lock package.
I don't really like synchronizing on a class attribute, but I guess that's just a matter of teste.
Synchronize on another static object that does not change:
public class PayloadService extends Service {
private static PayloadDTO payload = new PayloadDTO();
private static final Object lock = new Object();
public static void setPayload(PayloadDTO payload){
synchronized(lock){
PayloadService.payload = payload;
}
}
public static PayloadDTO getPayload() {
synchronized(lock){
return PayloadService.payload ;
}
}
Is this a correct/acceptable approach ?
No, the reason for this is that you should never synchronize on an variable/field that can change its value. That is, when you synchronize on PayloadService.payload and set a new PayloadService.payload, then you are violating a golden rule of synchronization.
You should either synchronize on the class instance or create some arbitrary private static final Object lock = new Object() and synchronize on that. You will have the same effect as synchronizing on the class.
There is a major part of functionality in this class which isn't posted which contributes to whether or not this approach is thread-safe: how do you access the PayloadDTO instance from the other parts of this class where it is used?
If you are providing methods which could swap in another instance for payload while another thread is running code which uses the payload object, then this is not thread safe.
For example if you have a method execute() which does the main work of this class and invokes methods on payload, you need to make sure that one thread cannot change the payload instance with the setter method while another thread is busy running execute().
In short, when you have shared state, you need to synchronize on all read and write operations on the state.
Personally I don't understand this approach and would never take it - providing static methods to allow other threads to re-configure a class smells like a violation of separation of concerns.