...
| Code Block | ||
|---|---|---|
| ||
public final class ConnectionFactory {
private static Connection dbConnection;
// Other fields ...
static {
Thread dbInitializerThread = new Thread(new Runnable() {
public void run() {
// Initialize the database connection
try {
dbConnection = DriverManager.getConnection("connection string");
} catch (SQLException e) {
dbConnection = null;
}
}
});
// Other initialization, for example, start other threads
dbInitializerThread.start();
try {
dbInitializerThread.join();
} catch (InterruptedException ie) {
throw new AssertionError(ie);
}
}
public static Connection getConnection() {
if (dbConnection == null) {
throw new IllegalStateException("Error initializing connection");
}
return dbConnection;
}
public static void main(String[] args) {
// ...
Connection connection = getConnection();
}
}
|
...
| Code Block | ||
|---|---|---|
| ||
public final class ConnectionFactory {
private static final ThreadLocal<Connection> connectionHolder
= new ThreadLocal<Connection>() {
public Connection initialValue() {
try {
Connection dbConnection = DriverManager.getConnection("connection string");
return dbConnection;
} catch (SQLException e) {
return null;
}
}
};
// Other fields ...
static {
// Other initialization (do not start any threads)
}
public static Connection getConnection() {
Connection connection = connectionHolder.get();
if (connection == null) {
throw new IllegalStateException("Error initializing connection");
}
return connection;
}
public static void main(String[] args) {
// ...
Connection connection = getConnection();
}
}
|
...
| Wiki Markup |
|---|
<ac:structured-macro ac:name="anchor" ac:schema-version="1" ac:macro-id="b653124c9501753d-097ba997-4f0144c0-874d9c16-a46e7a5a9abb3fd245e3fbbd"><ac:parameter ac:name="">CON03-EX1</ac:parameter></ac:structured-macro> *CON03-EX1:* It is permissible to start a background thread during class initialization provided the thread does not access any fields. For example, the {{ObjectPreserver}} class (based on \[[Patterns 02|AA. Java References#Patterns 02]\]) shown below provides a mechanism for storing object references, which prevents an object from being garbage-collected, even if the object is not dereferenced in the future. |
| Code Block | ||
|---|---|---|
| ||
public final class ObjectPreserver implements Runnable {
private static ObjectPreserver lifeLine = new ObjectPreserver();
private ObjectPreserver() {
Thread thread = new Thread(this);
thread.setDaemon(true);
thread.start(); // Keep this object alive
}
// Neither this class nor HashMap will be garbage-collected.
// References from HashMap to other objects will also exhibit this property
private static final ConcurrentHashMap<Integer,Object> protectedMap
= new ConcurrentHashMap<Integer,Object>();
public synchronized void run() {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // Reset interrupted status
}
}
// Objects passed to this method will be preserved until
// the unpreserveObject method is called
public static void preserveObject(Object obj) {
protectedMap.put(0, obj);
}
// Returns the same instance every time
public static Object getObject() {
return protectedMap.get(0);
}
// Unprotect the objects so that they can be garbage-collected
public static void unpreserveObject() {
protectedMap.remove(0);
}
}
|
...