Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to maintain mutable state in a Java Singleton

I have a Singelton in Java (in an OSGi Service) and want to maintain some state in it (a counter).

Should this variable be static? or synchronized? or both?

Or should i wrap the actions in a syncronized method? (would this be any different than just making the var syncronized?)

I want consumers of the service actions to increment this counter.

public MyServiceImpl implements MyService {
    private int count = 0; // static? syncronized?

    public String helloWorld() { count++; return "Hello World"; }
    public int getHelloCount() { return count; }
}

Update: How would I so something like a Map or a List? Is it preferred to use Atomic versions of these too? Or is Synchronized better for this?

like image 370
empire29 Avatar asked Dec 03 '25 16:12

empire29


2 Answers

The problem with singletons is that they require a scope. If you register a service in OSGi then this is a singleton in the framework. However, since OSGi avoids statics like the plague people could start multiple frameworks (nested or as siblings) in the same VM and that could mean your service gets registered multiple times in different frameworks. In general, this is exactly what you want. If this not sufficiently singleton, then what should be the scope? The VM, the process, the machine, the network, the world? All the tricks people provide you for creating singletons forget to tell you that they scope only for the class loader you happen to be in.

In OSGi, assume your scope is the framework. So just register a single service and use instance variables. Since OSGi runs in a concurrent environment, you must, as all the other posts indicate, use synchronized methods or better AtomicLong/AtomicInteger.

If you have multiple services that need to share a singleton, just create an extra service to represent the singleton.

Never use statics since they can reduce the reusability of your code significantly, they have all the evils of global variables. One of the beauties of pure OSGi is that it allows you program almost completely with instances and never have to work with statics and class names (which suffer from the same global variable problem).

like image 65
Peter Kriens Avatar answered Dec 06 '25 21:12

Peter Kriens


This is a perfect opportunity for using Atomics:

public class MyServiceImpl {
  private AtomicInteger helloCount = new AtomicInteger(0);

  public String helloWorld() {
    helloCount.incrementAndGet();
    return "Hello World";
  }

  public int getHelloCount() {
    return helloCount.get();
  }
}

This is lock-free and therefore generally faster and more efficient.

This mechanism will work just as well with singletons or non-singletons.

like image 23
OldCurmudgeon Avatar answered Dec 06 '25 21:12

OldCurmudgeon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!