I have modified a "normal" DCL singleton case according to "effective java" #83, as below.
import java.util.Date;
public class MySystem {
private Date date = new Date();
private MySystem() {};
private static volatile MySystem instance;
public Date getDate() {
return date;
}
public static MySystem getInstance() {
MySystem my = instance;
if (my == null) {
synchronized (MySystem.class) {
if (instance == null) {
instance = my = new MySystem();
}
}
}
return my;
}
}
But when I run it, NullpointerException will be throwed in a very high proportion. And when I modify it as below, everything is ok. Why?
import java.util.Date;
public class MySystem {
private Date date = new Date();
private MySystem() {};
private static volatile MySystem instance;
public Date getDate() {
return date;
}
public static MySystem getInstance() {
MySystem my = instance;
if (my == null) {
synchronized (MySystem.class) {
my = instance;
if (my == null) {
instance = my = new MySystem();
}
}
}
return my;
}
}
The main is as below. It's hard to figure out the difference.
public class Main {
public static void main(String[] args) {
new Thread() {
public void run() {
System.out.println(MySystem.getInstance().getDate());
}
}.start();
new Thread() {
public void run() {
System.out.println(MySystem.getInstance().getDate());
}
}.start();
}
}
You get NPE when the following happens:
public static MySystem getInstance() {
MySystem my = instance;
if (my == null) { // (1) instance was null => my is null and synchronized block is entered.
synchronized (MySystem.class) {
if (instance == null) { // (2) instance was updated from another thread and is not null anymore.
instance = my = new MySystem();
}
}
}
return my;
}
You will notice that in this scenario, the the reference instance is not copied into my, which remains null. You can try the following to verify:
public static MySystem getInstance() {
MySystem my = instance;
if (my == null) {
synchronized (MySystem.class) {
if (instance == null) {
instance = new MySystem();
}
}
my = instance;
}
return my;
}
The differnece is this line:
my = instance;
You're making both object reference one place on JVM's heap. After that you're calling:
my = new MySystem();
which makes both my and instance not null (you cannot chain = operator, so only my is instantiated). Then after calling this:
MySystem.getInstance().getDate()
you're not invoking method on null.
When it's synchronized, then the second thread is waiting for instantiation of my (for this line my = instance to be invoked) and doesn't get NPE.
Ok, let me to explain it step by step.
Thread A: my == null.
Thread B: my == null, then get sync, then "instance = my = new MySystem()", and return my, which is not null.
Thread A: get sync, then "instance != null", and return my, which is null.
NPE, bang! So the "my = instance" before second check is necessary.
How to explain the example in "Effective Java"?
// Double-check idiom for lazy initialization of instance fields
private volatile FieldType field;
private FieldType getField() {
FieldType result = field;
if (result == null) { // First check (no locking)
synchronized(this) {
if (field == null) // Second check (with locking)
field = result = computeFieldValue();
}
}
return result;
}
Related
I want to implement a method which has a different behavior when called for the first time, and then when it is called for the second time.
How to do that?
Instance methods in Java have access to the state of the class. Add a variable to indicate whether or not the methods has been called before, and use it to decide between two paths to take inside the method:
class FirstTimeCaller {
private boolean isFirstTime = true;
void methodWithState() {
if (isFirstTime) {
... // Do first-time thing
isFirstTime = false;
} else {
... // Do the other thing
}
}
}
This works for instance methods of the same object: first-time call will be executed the first time you call methodWithState on each new object of FirstTimeCaller class.
If you wish to implement the same behavior for a static method, or you'd like to have the first invocation on any instance to do a different thing, and all subsequent calls to do something else, make isFirstTime field static.
You can simply create a variable
int counter = 0; // This means the method has not been called yet
And when the method is called then just do this code in it:
counter++; // Increment by 1 for each new call
And you have a number of method calls stored in a variable "counter" so you can choose what to do with it.
Just to extend the list of possible solutions, you may as well consider the State-Pattern:
public class Sandbox {
private Runnable delegate = () -> {
System.out.println("First Time");
delegate = () -> System.out.println("Second Time");
};
public synchronized void doIt() {
delegate.run();
}
}
public class MethodLogic implements Callable<String> {
private boolean called = false;
public String call() {
if (!called) {
called = true;
return "first";
} else {
return "not first";
}
}
}
Later use it like
Callable<String> method = new MethodLogic();
System.out.println(method.call());
System.out.println(method.call());
If called in a multi-threaded context, you got to be careful with concurrent access. You can for instance use an AtomicBoolean:
public class FirstAndSecondTime {
private static final AtomicBoolean FIRST_TIME = new AtomicBoolean(true);
public void perform() {
if (FIRST_TIME.compareAndSet(true, false)) {
//execute first time logic here
} else {
//execute 2-n time logic here
}
}
}
Using a static class:
public class MyStaticClass {
private static boolean firstTime = true;
public static void myMethod() {
if (firstTime) {
System.out.println("First time");
} else {
firstTime = false;
System.out.println("NOT first time");
}
}
}
Then you'd use it like this:
MyStaticClass.myMethod(); //-> prints "First time"
MyStaticClass.myMethod(); //-> prints "NOT first time"
MyStaticClass.myMethod(); //-> prints "NOT first time"
This is how the Singleton design pattern does it with lazy initialization:
public final class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
if (instance == null) {
instance = new Singleton();
}
}
return instance;
}
}
You should probably not use this (unless you're using it for a Singleton, I guess), but use a field on an object:
public class MyMessagePrinter {
private int counter = 0;
public void printMessage() {
if (this.counter > 0) {
System.out.println("Fist time");
} else {
System.out.println("NOT first time");
}
}
}
Using it like this:
MyMessagePrinter myPrinter = new MyMessagePrinter();
myPrinter.print(); //-> prints "First time"
myPrinter.print(); //-> prints "NOT first time"
myPrinter.print(); //-> prints "NOT first time"
Make note that the code is not thread safe
I outputted the same object at the same time but I got different results...
What could be the cause of DIFFERENT result?
The function in UserHelper.class:
public void login(String phone, String password) {
UserModel.logInInBackground(phone, password, new LogInCallback<UserModel>() {
#Override
public void done(UserModel userModel, AVException e) {
if (null != userModel) {
if (userModel.getPosition() == UserModel.USER_BUYER) {
refresh();
DebugLog.e("fuck" + mUserStatus + UserInstance.getInstance().getUserStatus());
for (UserListener listener : listeners)
listener.OnUserLogin();
} else if (userModel.getPosition() == UserModel.USER_SELLER)
logout();
} else for (UserListener listener : listeners)
listener.HandleError(e.getCode());
}
}, UserModel.class);
public USER_STATUS getUserStatus() {
return mUserStatus;
}
And the UserInstance.class.
public class UserInstance {
public static UserHelper mInstance;
public static UserHelper getInstance() {
if (null == mInstance) mInstance = new UserHelper();
DebugLog.e(mInstance.toString());
return mInstance;
}
}
First of all, if you meant the UserHelper class to be a singleton,
why do you access the USER_STATUS instance using UserInstance.getInstance().getUserStatus() instead of just getUserStatus() ?
Second of all, you probably get different instances of UserHelper if the singleton is accessed from different threads, because your implementation is not thread-safe.
A correct implementation would be using a double locking pattern:
public class UserInstance {
public static UserHelper mInstance;
private static final ReentrantLock lock = new ReentrantLock();
public static UserHelper getInstance() {
if (null == mInstance){
lock.lock();
try{
if (null == mInstance){
mInstance = new UserHelper();
}
}
finally{
lock.unlock();
}
}
DebugLog.e(mInstance.toString());
return mInstance;
}
}
Ultimately, I get the same instance..
Thanks to Shlomi Uziei. I forgot to use double locking pattern. And I should not make mInstance static...
I have Constants class in my web application.
I want to monitor Constants class using Jconsole.
I have #ManagedResource used annotation for Constants class and #ManagedAttributefor setter method.
If I will use #ManagedAttribute for static method then it will not displayed in Jconsole and for non-static method it works fine.
Can you please provide explanation why it was not working with static method?
Following is my Constants class.
#ManagedResource(
objectName = "Sample:name=ActivityQueueUtil",
description = "Allows modifying all settings."
)
public class ActivityQueueUtil {
private static volatile ActivityQueueUtil instance;
public static ActivityQueueUtil getInstance() {
if (instance == null ) {
synchronized (Constants.class) {
if (instance == null) {
instance = new ActivityQueueUtil();
}
}
}
return instance;
}
public void initInstance() {
instance = this;
}
private int currentWorkerCount = 0;
private int currentQueueSize = 0;
private int currentRetryQueueSize = 0;
#ManagedAttribute(description = "Current number of worker threads.")
public static int getCurrentWorkerCount() {
return currentWorkerCount;
}
public void setCurrentWorkerCount(int currentWorkerCount) {
this.currentWorkerCount = currentWorkerCount;
}
#ManagedAttribute(description = "Number of activities in the queue")
public int getCurrentQueueSize() {
return currentQueueSize;
}
}
Here it works for setCurrentWorkerCount,getCurrentQueueSize but not working for getCurrentWorkerCount
Singleton is a service that require injection of authentication and configuration data. I end with class:
class SingleService {
private String conn;
private String user;
private String pass;
private SingleService() {
// Can throw exception!!
conn = Config.getProperty("conn");
user = Config.getProperty("user");
pass = Config.getProperty("pass");
// Can throw exception!!
internalService = tryConnect(conn, user, pass);
}
private static SingleService instance;
public static void init() {
instance = new SingleService();
}
public static synchronized SingleService getInstance() {
if (instance == null) init();
return instance;
}
}
Dedicated init() method used for exception handling during application startup to early detect initialization errors early because later we just call getInstance() and doesn't expect to get errors:
class App {
public static void main(String args[]) {
try {
Config.init("classpath:auth.properties");
SingleService.init();
} catch (Exception ex) {
logger.error("Can't init SingleService...");
System.exit()
}
doJob();
}
private static void doJob() {
SingleService.getInstance().doJob();
}
}
I worry about init() method and singleton class signature. Fill that class was designed badly but don't understand what's wrong.
Is it possible to move away initialization from getSingleton() and synchronized and preserving control on exception during initialization?
This is how I would code it so you can throw exceptions if needed but still have a thread safe singleton.
enum SingleService {
INSTANCE;
private String conn;
private String user;
private String pass;
private SingleService instance;
public synchronized void init(Config config) throws SomeException {
// don't leave in a half state if we fail.
internalService = null;
conn = config.getProperty("conn");
user = config.getProperty("user");
pass = config.getProperty("pass");
internalService = tryConnect(conn, user, pass);
}
public synchronized void methodForService() {
if (internalService == null) throw new IllegalSateException();
// do work.
}
}
SingleService ss1 = SingleService.getInstance();
SingleService.init();
SingleService ss2 = SingleService.getInstance();
So ss1 is a different object than ss2 which is not what Singleton is designed for. If ss1 is modified at anytime ss2 will remain unaffected.
Fist of all you souhld not expose object creation method. If you want to check something, than go with asserts or any operation that will not corrupt instance object.
public static void checkIfValid() {
assert Config.getProperty("conn");// do not corrupt instance object
assert Config.getProperty("user");
assert Config.getProperty("pass");
}
public static synchronized SingleService getInstance() {
if (instance == null){ // only here you can initiate instance object
instance = new SingleService();
}
return instance;
}
My production code for problem I have sought:
public abstract class AbstractCaller<Port> {
abstract protected Port createPort();
protected init() {
Port port = createPort();
// heavy use of introspection/reflection on **port** object.
// Results are used later by **call** method.
}
public call() {
// Reflection based on data collected by **init** method.
}
}
public class ConcreteCaller extends AbstractCaller<ConcretePort> {
private ConcreteService service = new ConcreteService();
#Override
protected ConcretePort createPort() {
return service.getPort();
}
private static class Holder {
public static ConcreteCaller INSTANCE;
static {
INSTANCE = new ConcreteCaller();
INSTANCE.init();
}
}
public static Caller getInstance() {
return Holder.INSTANCE;
}
}
Abstract class has common init method that can only operate on fully initialized concrete class. Inner static class is used for lazy instantiation and perform init invocation.
There is no way to apply init method from superclass constructor to avoid need to call init in each implementation.
I have an example code of Singleton class inheritance below. However, I've not forseen if there's any hidden issue might happen with this code. Can someone analyze and give me a hint?
interface ChairIF {
public int getLeg();
public void test();
}
class ChairImpl implements ChairIF {
private static final Lock lock = new ReentrantLock();
private static ChairIF instance = null;
public static ChairIF getInstance(String clazzName) {
//get class by clazzName
Class clazz = null;
try {
clazz = Class.forName(clazzName);
} catch (ClassNotFoundException ex) {
lock.lock();
try {
if (instance == null) {
instance = new ChairImpl();
}
} finally {
lock.unlock();
}
}
//init singleton instance of clazzName
if (instance == null) {
lock.lock();
try {
if (instance == null) {
instance = (ChairIF) clazz.newInstance();
} else {
if (instance.getClass() != clazz) {
instance = (ChairIF) clazz.newInstance();
}
}
} catch (Exception ex) {
instance = new ChairImpl();
} finally {
lock.unlock();
}
} else {
lock.lock();
try {
if (!instance.getClass().getName().equals(clazz.getName())) {
instance = (ChairIF) clazz.newInstance();
}
} catch (Exception ex) {
instance = new ChairImpl();
} finally {
lock.unlock();
}
}
return instance;
}
public int getLeg() {
return 4;
}
public void test() {
throw new UnsupportedOperationException();
}
}
class ThreeLegChair extends ChairImpl {
public ThreeLegChair() {}
public int getLeg() {
return 3;
}
public void test() {
int i = 0;
while(i < 10000) {
System.out.println("i: " + i++);
}
}
}
class NoLegChair extends ChairImpl {
public NoLegChair() {}
public int getLeg() {
return 0;
}
public void test() {
int j = 0;
while(j < 5000) {
System.out.println("j: " + j++);
}
}
}
public class Test {
public static void main(String[] args) {
System.out.println(ChairImpl.getInstance("ThreeLegChair").getLeg());
System.out.println(ChairImpl.getInstance("NoLegChair").getLeg());
/***
TODO: build logic to run 2 test() simultaneously.
ChairImpl.getInstance("ThreeLegChair").test();
ChairImpl.getInstance("NoLegChair").test();
****/
}
}
As you can see, I did put some test code in 2 subclasses. ThreeLegChair is to loop from 0 to 10000 and print it out. NoLegChair is to loop only from 0 to 5000 and print it out.
The result I got in the console log is correct. ThreeLegChair printed i from 0 to 10000. NoLegChair printed j from 0 to 5000.
Please share me your thought :)
Singleton pattern is achieved using the concept of private constructor i.e. the class itself is responsible for creating single instance of the class (singleton) and preventing other classes from creating objects.
Now as the constructor is private, you cannot inherit the singleton class at first place. In your case, I do not see a private constructor which makes it vulnerable to object creation from other classes accessing it.
Singleton pattern examples:
Using enumerations in Java
enum SingletonEnum {
SINGLE_INSTANCE;
public void doStuff() {
System.out.println("Singleton using Enum");
}
}
Lazy initialization approach
class SingletonClass {
private static SingletonClass singleInstance;
private SingletonClass() {
// deny access to other classes
}
// The object creation will be delayed until getInstance method is called.
public static SingletonClass getInstance() {
if (null == singleInstance) {
// Create only once
singleInstance = new SingletonClass();
}
return singleInstance;
}
}
However, the above example may not guarantee singleton behavior in multithreaded environment. It is recommended to use double checked locking mechanism to ensure that you have created a single instance of this class.
The code you post isn't an implementation of the singleton pattern.
Quite simply, you can do:
ChairImpl ci = new ChairImpl();
And instantiate as many as you want.
The traditional method of implementing the singleton pattern is the make the constructor private, have a private static field that holds the single instance of the class, and a static getInstance() method that either instantiates that instance or returns the existing one. Making that threadsafe involves either declaring it synchronized or using a locking scheme.
The private constructor bit makes it so you can't inherit from it.
That said, in Java the preferred way is using an enum which provides all the hard parts for free:
public enum MySingleton {
INSTANCE;
public int getLeg() {
return 4;
}
}
And using as:
MySingleton ms = MySingleton.INSTANCE;
int leg = ms.getLeg();
Singletons usually have private constructor. Your class is not following proper Singleton pattern. otherwise you would not be inherit your singleton class.