Using Synchronization while Logging
java, logging, multithreading
Solution
I agree with other commenters that lazy initialization doesn't seem necessary here. The simplest way to initialize the logger variable is in a static initializer, which is guaranteed to only execute once at class loading time:
public class Logger {
public final static String PROPERTIES_FILE = "Logger.properties";
private static java.util.logging.Logger logger = null;
private static void initialize() {
try {
logger = java.util.logging.Logger.getLogger(Logger.class.getName());
FileHandler fh = new FileHandler("D:\\MyLogFile.log", true);
logger.addHandler(fh);
logger.setLevel(Level.ALL);
SimpleFormatter formatter = new SimpleFormatter();
fh.setFormatter(formatter);
logger.log(Level.INFO, "Test Message Logged");
}
catch (IOException e) {
System.out.println("Warning: Unable to read properties file " +
PROPERTIES_FILE );
}
}
static {
initialize();
}
public static java.util.logging.Logger getLogger(String name)
{
logger.getLogger(name);
return logger;
}
}
However, You can avoid most synchronization with double-checked locking.
public class Logger {
// note: volatile is required
private volatile static java.util.logging.Logger logger = null;
//...
public static java.util.logging.Logger getLogger(String name)
{
if(logger==null)
{
synchronized(Logger.class)
{
if(logger == null)
Logger.initialize();
}
}
}
logger.getLogger(name);
return logger;
}
}
In fact, in your case I think you can avoid synchronization altogether if you rewrite your initialize function so that it completely configures the logger in an local variable prior to assigning it to the (volatile) class variable:
private volatile static java.util.logging.Logger logger = null;
private static void initialize() {
try {
Logger logger = java.util.logging.Logger.getLogger(Logger.class.getName());
FileHandler fh = new FileHandler("D:\\MyLogFile.log", true);
logger.addHandler(fh);
logger.setLevel(Level.ALL);
SimpleFormatter formatter = new SimpleFormatter();
fh.setFormatter(formatter);
logger.log(Level.INFO, "Test Message Logged");
Logger.logger = logger;
}
catch (IOException e) {
System.out.println("Warning: Unable to read properties file " +
PROPERTIES_FILE );
}
public static java.util.logging.Logger getLogger(String name)
{
if(logger==null)
{
Logger.initialize();
}
logger.getLogger(name);
return logger;
}
}
This has a potential to have initialize() execute several times, but I don't think you care, so long that every getLogger invocation will have a valid logger instance, even if that instance varies.
Problem
In my application I have written my own Logging utility using Java.Util.Logging ``` import java.io.IOException; import java.io.InputStream; import java.util.Properties; import java.util.logging.FileHandler; import java.util.logging.Level; import java.util.logging.SimpleFormatter; public class Logger { public final static String PROPERTIES_FILE = "Logger.properties"; private static java.util.logging.Logger logger = null; private static void initialize() { try { logger = java.util.logging.Logger.getLogger(Logger.class.getName()); FileHandler fh = new FileHandler("D:\\MyLogFile.log", true); logger.addHandler(fh); logger.setLevel(Level.ALL); SimpleFormatter formatter = new SimpleFormatter(); fh.setFormatter(formatter); logger.log(Level.INFO, "Test Message Logged"); } catch (IOException e) { System.out.println("Warning: Unable to read properties file " + PROPERTIES_FILE ); } } public static synchronized java.util.logging.Logger getLogger(String name) { if(logger==null) { Logger.initialize(); } logger.getLogger(name); return logger; } } ``` Do I need to use Synchronization for getLogger method? Please give your comments. (This code is running in Multi-threaded environment)