I want to have a static field in a class to be automatically initialized when another class is loaded.
Something like this:
class ServiceBase {
static Object lock = new Object();
static ServiceBase service;
static void setService(ServiceBase service) {
synchronized (lock) {
ServiceBase.service = service;
lock.notifyAll();
}
}
void f() throws Exception {
synchronized (lock) {
while (service == null){
lock.wait();
}
}
//use service
}
}
class ServiceImpl extends ServiceBase {
static {
ServiceBase.setService(ne ServiceImpl());
}
}
The problem is that is f is called before ServiceImpl is loaded, it hangs in a deadlock.
What's the best way of initializing the service instance? (I cannot use Spring or other huge frameworks)
Your approach is overly complex. You should not need to worry about synchronization or any of that.
The most obvious simplification is to pass the Service instance as a constructor parameter to ServiceBase:
class ServiceBase {
private final Service service;
ServiceBase(Service service) {
this.service = checkNotNull(service);
}
void f() {
// service is guaranteed to be present.
}
}
This way, you can never actually call f() before a non-null service is available.
If your concern is that you want the same instance of ServiceImpl to be used every time, create a ServiceBaseProvider class which you use to get instances of ServiceBase, instead of constructing them directly:
class ServiceBaseProvider {
private static ServiceImpl INSTANCE = new ServiceImpl();
static ServiceBase getInstance() {
return new ServiceBase(INSTANCE);
}
}
Or, of course, inject the same instance of ServiceBase wherever it is required, which makes it much easier to (for example) inject a mock instance during tests.
Related
I create a hierarchy from an abstract class and two children that are used in class F and pass them to the service
#Getter
abstract class A {
private final B b;
public A(B b) {
this.b = b;
}
abstract void doSomething();
}
#Getter
class B {
private final String someProperty;
}
class C extends A {
public C(B b) {
super(b);
}
#Override
void doSomething() {
super.getb().getSomeProperty();
}
}
class D extends A {
public D(B b) {
super(b);
}
#Override
void doSomething() {
super.getb().getSomeProperty();
}
}
#RestController
class F {
#Autowired
private Service service;
#GetMapping
public void methodOne() {
A a1 = new C(new B("ccc"));
service.make(a1);
}
#GetMapping
public void methodTwo() {
A a1 = new D(new B("ddd"));
service.make(a1);
}
}
#Service
public class Service {
public void make(A a) {
a.doSomething();
}
}
The construction that I described above in case we have a lot of clients who call our API will there be any problems in thread safety with the state of our abstract class or not?
"Thread Safety" thing comes into the picture when multiple threads are trying to manipulate same object and by allowing to do so may end up with inconsistent state of the Object which is obviously not acceptable for any application.
Your question is about the Object you've declared in your abstract parent class, now as I said earlier the problem will only be there if multiple threads are using the same object, since you're creating new objects every time the service method is getting called, you are safe why?, because the scope of the object is limited to the method and multiple threads can not use the same object as for each method call you'll have a different object.
Now consider this case, in this case thread safety is a concern,
#Service
class UnSafeClass {
private MyClass myClassObject;
public void doSomething() {
myClassObject.changeData();//Same object will be used by multiple threads
}
}
So, your current implementation does not have any thread safety concerns but we should definitely need to clarify on where exactly you need to take care of thread safety.
So I have the following scenario (can't share the actual code, but it would be something like this):
public class Test
{
private Object obj;
public void init()
{
service.registerListener(new InnerTest());
}
public void readObj()
{
// read obj here
}
private class InnerTest implements Listener
{
public synchronized void updateObj()
{
Test.this.obj = new Object();
// change the obj
}
}
}
The InnerTest class is registered as listener in a service. That Service is running in one thread the calls to readObj() are made from a different thread, hence my question, to ensure consistency of the obj is it enough to make the UpdateObj() method synchronized?
I would suggest using another object as a lock to ensure that the class only blocks when the obj is accessed:
public class Test
{
private final Object lock = new Object();
private Object obj;
public void init()
{
service.registerListener(new InnerTest());
}
public void readObj()
{
synchronized(lock){
// read obj here
}
}
private class InnerTest implements Listener
{
public void updateObj()
{
synchronized(Test.this.lock){
Test.this.obj = new Object();
// change the obj
}
}
}
}
Then use that lock in all methods that need to have consistent access to obj. In your current example the readObj and updateObj methods.
Also as stated in the comments, using synchronized on the method level in your InnerTest class, will not really work as you probably intended. That is, because synchronized methods will use a synchronized block on the this variable. Which just blocks your InnerTest class. But not the outer Test class.
This is my first post on here so I will try to be precise. This is for a university project, we have to create a fish tank simulation on top of an OO architecture that we individually make. I'm exploring the uses of singletons and have found them quite useful, however reading online the way I currently implement it is not thread safe.
The way I currently implement it (Think its the lazy method) Note: We have to go through the interface
public interface myInterface
{
void foo();
}
public class myClass implements myInterface
{
private static myInterface instance;
private myClass(){}
private static myInterface Instance()
{
if(instance == null)
instance = new myClass();
return instance;
}
public void foo()
{
//Do stuff
}
public void bar()
{
//Do More Stuff
}
}
This works well however its not thread safe I could add the synchronized keyword to the getter but I've read that that is quite heavy on the system and I have quite a few singletons.
private synchronized static myInterface Instance()
{
if(instance == null)
instance = new myClass();
return instance;
}
I have then moved on to an enum singleton which is thread safe and is not heavy on the system however I am unsure on how to program it to the interface.
public enum myClass implements myInterface
{
INSTANCE;
private myClass(){}
public void foo()
{
//Do stuff
}
public void bar()
{
//Do More Stuff
}
}
In programming to the interface I mean when I call the singleton I can only access methods that are in the interface (please correct me if I'm referring to this wrongly). This is where the way I have done the enum singleton fails. For example: With the lazy singleton I can not call this as its not in the interface:
myClass.Instance().bar();
But it can call this which is correct, as it is in the interface.
myClass.Instance().foo();
With the enum however I can call this and its not programming to the interface
myClass.INSTANCE.bar();
I understand why its doing this as the class is an enum so it will be able to call everything in that enum class. So after this long post which I apologise for, the main question is: Can I make the enum version only call methods that are declared in the interface?
If it can't how heavy is a synchronized method on the system, I would have around 4-6 of them?
Please Note: Even though this is for a university project we are only running the simulation on one thread so it does not even need to be thread safe. I don't quite understand multi-threading but I thought it would be a good learning opportunity.
You can always hide your enum implementation as well if you prefer the enum route:
public interface Singleton {
void foo();
}
public final class SingletonAccessor {
public static Singleton getInstance() {
return SingletonImpl.INSTANCE;
}
private SingletonAccessor() {
}
private enum SingletonImpl implements Singleton {
INSTANCE;
public void foo() {
// ...
}
public void bar() {
// ...
}
}
}
EDIT
As pointed out by Peter Lawrey in the comments, you can even use an enum for the SingletonAccessor :)
public enum SingletonAccessor {
SINGLETON;
public Singleton get() {
return SingletonImpl.INSTANCE;
}
private enum SingletonImpl implements Singleton {
INSTANCE;
public void foo() {
// ...
}
public void bar() {
// ...
}
}
}
You can cast it to the interface or
myInterface my = myClass.INSTANCE;
my.foo();
You can still use a method like
myClass.getInstance().foo();
But this isn't a real solution IMHO.
Can I make the enum version only call methods that are declared in the interface?
Ultimately you have to decide which methods you want on the instance which are public. If you make a method or field public, you can access it and if you don't want to be able to access it, make it private.
At some point you have to trust you know what you are doing and you do things for a reason. You don't have to think up ways to prevent yourself from call code you wrote.
just simply change your singleton class this way:
public class myClass implements myInterface
{
private static myInterface instance = new myClass();
private myClass(){}
private static myInterface Instance()
{
return instance;
}
public void foo()
{
//Do stuff
}
public void bar()
{
//Do More Stuff
}
}
this will assure that the singleton object will be created at class-loading time, and you don't need to worry about race-conditions in the Instance() method
Try looking at java.util.concurrent.atomic.AtomicReference. Specifically compareAndSet.
instance.compareAndSet(null, new MyClass());
That is if your instance field is null, set to new object, if not null, leave intact. Should be less heavy.
I have two singleton classes, lets call them class A and class B.
The classes look like such.
class A
{
private static A instance;
private A(int timeout)
{
init();
}
public static A getInstance(int timeout)
{
if(instance == null)
{
instance = new A(timeout);
}
return instance;
}
private void init()
{
new Monitor().sendMonitorStatus();
}
}
and for class B
class B
{
private static B instance;
private B(A a)
{
}
public static B getInstance(A a)
{
if(instance == null)
{
instance = new B(a);
}
return instance;
}
}
Then there is a class named Monitor as well that looks as such.
class Monitor
{
public void sendMonitorStatus()
{
B.getinstance(A.getinstance(10));
}
}
The problem as you can see, is that I get a stackoverflow since it keeps a cycle of a call to B then calling A which calls B which calls A..., is there anyway to solve this problem without a redesign or is the only way to solve this cycle causing this error to redesign how the classes work?
To create an instance of A, you need to call Monitor::sendMonitorStatus. To call Monitor::sendMonitorStatus, you need an instance of A. You have a dependency cycle.
You need to redesign this. Exactly how – it depends on what you want to achieve.
Consider this code:
public class A {
private static final A INSTANCE = new A();
public static A getInstance() {
return INSTANCE;
}
private A() {}
public void doSomething() {}
}
// elsewhere in code
A.getInstance().doSomething();
How do I do the same when A requires a spring bean for construction? I don't want to inject A in each class that needs it, but want those classes to be able to access the singleton instance statically (ie, A.getInstance()).
Accessing a Spring bean from a static context is problematic because the initialization of beans isn't tied to their construction, and Spring may instrument injected beans by wrapping them in proxies; simply passing around references to this will often result in unexpected behaviour. It's best to rely on Spring's injection mechanism.
If you really have to do it (perhaps because you need access from legacy code), use something like this:
#Service
public class A implements ApplicationContextAware {
private static final AtomicReference<A> singleton;
private static final CountDownLatch latch = new CountDownLatch(1);
#Resource
private MyInjectedBean myBean; // inject stuff...
public static A getInstance() {
try {
if (latch.await(1, TimeUnit.MINUTES)) {
return singleton.get();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
throw new IllegalStateException("Application Context not initialized");
}
#Override
public void setApplicationContext(ApplicationContext context) {
singleton.set(context.getBean(A.class));
latch.countDown();
}
}