Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force a Java thread to close a thread-local database connection

When Using a thread-local database connection, closure of the connection is required when the thread exists.

This I can only do if I can override the run() method of the calling thread. Even that is not a great solution, since at time of exit, I don't know if a connection has ever been opened by that thread.

The problem is in fact more general: How to force a thread to call some finalisation method of a thread-local object when it exits.

I looked at the sources of java 1.5 and found that the thread local map is set to null, which will eventually cause the garbage collection to call finalize(), but I don't want to count on the garbage collector.

The following override seems inevitable to make sure that a database connection is closed:

@Override 
public void remove() {
    get().release(); 
    super.remove(); 
}

where release() closes the database connection, if it has been opened. But we don't know if the thread has ever used this thread-local. If get() has never been called by this thread, then there's quite a waste of effort here: ThreadLocal.initialValue() will be called, a map will be created on this thread, etc.


Further clarification and example as per Thorbjørn's comment:

java.lang.ThreadLocal is a type of factory for an object that is bound to a thread. This type has a getter for the object and a factory method (typically written by the user). When the getter is called it calls the factory method only if it has never been called before by this thread.

Using ThreadLocal allows a developer to bind a resource to a thread even if the thread code was written by a third party.

Example: Say we have a resource Type called MyType and we want to have one and only one of it per thread.

Define in the using class:

private static ThreadLocal<MyType> resourceFactory = new ThreadLocal<MyType>(){
    @override
    protected MyType initialValue(){
        return new MyType();
    }
}

Use in local context in this class:

public void someMethod(){
    MyType resource = resourceFactory.get();
    resource.useResource();
}

get() can call initialValue() only once in the life cycle of the calling thread. At that point an instance of MyType gets instantiated and bound to this thread. Subsequent calls to get() by this thread refer again to this object.

The classic usage example is when MyType is some thread-unsafe text/date/xml formatter.

But such formatters usually don't need to be released or closed, database connections do and I am using java.lang.ThreadLocal to have a one database connection per thread.

The way I see it, java.lang.ThreadLocal is almost perfect for that. Almost because there's no way to guarantee closure of the resource if the calling thread belongs to a third party application.

I need your brains squires: By extending java.lang.ThreadLocal I managed to bind one database connection for every thread, for it's exclusive usage - including threads that I can not modify or override. I managed to make sure that the connections get closed in case the thread dies on uncaught exception.

In case of normal thread exit, the garbage collector closes the connection (because MyType overrides the finalize()). In actual fact it happens quite quickly, but this is not ideal.

If I had my way, there would have been another method on the java.lang.ThreadLocal:

protected void release() throws Throwable {}

If this method existed on java.lang.ThreadLocal, called by JVM upon any thread exit/death, then in my own override of it I could close my connection (and the redeemer would have come to Zion).

In the absence of such method, I'm looking for another way to confirm closure. A way that won't rely on the JVM garbage collection.

like image 931
Joel Shemtov Avatar asked Nov 09 '09 10:11

Joel Shemtov


People also ask

What is threadLocal in Java?

The ThreadLocal class is used to create thread local variables which can only be read and written by the same thread. For example, if two threads are accessing code having reference to same threadLocal variable then each thread will not see any modification to threadLocal variable done by other thread.

How do you stop a direct execution of a thread in Java?

The stop() method is deprecated. It forces the thread to stop executing.

What stops the execution of a thread in Java?

Whenever we want to stop a thread from running state by calling stop() method of Thread class in Java. This method stops the execution of a running thread and removes it from the waiting threads pool and garbage collected. A thread will also move to the dead state automatically when it reaches the end of its method.

Will thread automatically be killed?

A thread is automatically destroyed when the run() method has completed. But it might be required to kill/stop a thread before it has completed its life cycle. Previously, methods suspend(), resume() and stop() were used to manage the execution of threads.


1 Answers

If you are of a sensitive disposition, look away now.

I wouldn't expect this to scale very well; it effectively doubles the number of threads in the system. There may be some use cases where it is acceptable.

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 and so on is left as an exercise for the implementer.

You could also have a look at tracking the threads/resources in a ConcurrentHashMap with another thread polling isAlive. But that solution is the last resort of the desperate - objects will probably end up being checked too often or too seldom.

I can't think of anything else that doesn't involve instrumentation. AOP might work.

Connection pooling would be my favoured option.

like image 196
McDowell Avatar answered Oct 24 '22 05:10

McDowell