How to force a java thread to close a thread local database connection
When using thread local database connection, the connection needs to be closed when the thread exists
I can do this only if I override the run () method of the calling thread Even if this is not a good solution, because when I exit, I don't know whether the connection has been opened by the thread
The problem is general: how to force the thread to call some finalization methods when the thread local object exits
I checked the source code of Java 1.5 and found that the thread local map is set to null, which will eventually lead to the garbage collection calling finalize (), but I don't want to count on the garbage collector
The following overrides seem inevitable to ensure that the database connection is closed:
@Override public void remove() { get().release(); super.remove(); }
Release() closes the database connection, if it is already open But we don't know if the thread has ever used this thread's local If this thread does not call get (), it will consume a lot of energy here: ThreadLocal Initialvalue () will be called and a map will be created on this thread
–
Further clarification and examples based on thorbj ø RN's comments:
java. Lang. ThreadLocal is a factory type of objects bound to threads This type has getters and factory methods for objects (usually written by the user) When a getter is called, it calls the factory method only if it has never been called by this thread
Using ThreadLocal allows developers to bind resources to threads, even if the thread code is written by a third party
For example, we have a resource type named mytype. We want only one for each thread
Define in the usage class: private static ThreadLocal resourcefactory = new threadlocal() {@ override protected mytype initialvalue() {return new mytype();}}
Use local context in this course: public void somemethod() {mytype resource = resourcefactory. Get(); resource. Useresource();}
Get () can call initialValue () once in the lifecycle of the calling thread. At this point, the instance of mytype is instantiated and bound to this thread Then call get () through this thread to refer to this object again
The classic use example is when mytype is some thread unsafe text / date / XML formatter
However, such formatter usually does not need to be released or closed, database connection and I am using Java Lang. ThreadLocal each thread has a database connection
The way I see it, Java Lang. ThreadLocal is almost perfect Almost because if the calling thread belongs to a third-party application, there is no guarantee that the resource will be closed
I need your brain: by extending Java Lang. ThreadLocal I try to bind a database connection for each thread because it is exclusive - including threads that I cannot modify or overwrite I try to ensure that the connection is closed to prevent the thread from dying in an uncapped exception
When the normal thread exits, the garbage collector closes the connection (because mytype overrides finalize()) In fact, it happens quickly, but it's not ideal
If I have my way, then in Java There is another method in lang.threadlocal:
protected void release() throws Throwable {}
If this method exists in Java Lang. ThreadLocal, called by the JVM when any thread exits / dies, and then in my own overwrite, I can close my connection (the Redeemer will come to Zion)
Without this method, I am looking for another way to confirm the shutdown A method that does not rely on JVM garbage collection
thank you
Solution
If you are a sensitive disposition, look now
I don't expect this ratio to be good; It effectively doubles the number of threads in the system There may be some acceptable use cases
public class Estragon { public static class Vladimir { Vladimir() { System.out.println("Open"); } public void close() { System.out.println("Close");} } private static ThreadLocal<Vladimir> HOLDER = new ThreadLocal<Vladimir>() { @Override protected Vladimir initialValue() { return createResource(); } }; private static Vladimir createResource() { final Vladimir resource = new Vladimir(); final Thread godot = Thread.currentThread(); new Thread() { @Override public void run() { try { godot.join(); } catch (InterruptedException e) { // thread dying; ignore } finally { resource.close(); } } }.start(); return resource; } public static Vladimir getResource() { return HOLDER.get(); } }
Better error handling, etc. as an exercise for implementers
You can also view the concurrent HashMap that tracks threads / resources and another thread polling isalive But the solution is a last resort to despair - objects may end up being checked too often or too little
I can't think of anything that doesn't involve instruments AOP may work
Connection pool will be my favorite choice