При использовании подключения к локальной сети с потоком требуется соединение с соединением, если существует поток.
Это я могу сделать, только если я могу переопределить метод run() вызывающего потока. Даже это не является отличным решением, так как во время выхода я не знаю, было ли соединение когда-либо открыто этим потоком.
Проблема на самом деле более общая: как заставить поток вызывать некоторый метод финализации потока-локального объекта при его выходе.
Я посмотрел на источники java 1.5 и обнаружил, что локальная карта потока установлена в нуль, что в конечном итоге приведет к тому, что сбор мусора вызовет finalize(), но я не хочу рассчитывать на сборщик мусора.
Следующее переопределение кажется неизбежным, чтобы убедиться, что соединение с базой данных закрыто:
@Override
public void remove() {
get().release();
super.remove();
}
где release() закрывает соединение с базой данных, если оно было открыто. Но мы не знаем, использовал ли поток этот поток-локальный. Если get() никогда не был вызван этим потоком, здесь здесь будет довольно тратить силы: Будет вызван ThreadLocal.initialValue(), в этом потоке будет создана карта и т.д.
-
Дальнейшее разъяснение и пример в соответствии с комментарием Торбьерна:
java.lang.ThreadLocal - это тип factory для объекта, связанного с потоком. Этот тип имеет getter для объекта и метод factory (обычно написанный пользователем). Когда геттер называется, он вызывает метод factory только в том случае, если этот поток никогда не вызывался этим потоком.
Использование ThreadLocal позволяет разработчику связывать ресурс с потоком, даже если код потока был написан третьей стороной.
Пример: Скажем, у нас есть тип ресурса, называемый MyType, и мы хотим иметь один и только один из них для каждого потока.
Определите в используемом классе: private static ThreadLocal resourceFactory = new ThreadLocal() { @Override protected MyType initialValue() { return new MyType(); } }
Использовать в локальном контексте в этом классе: public void someMethod() { Ресурс MyType = resourceFactory.get(); resource.useResource(); }
get() может вызывать initialValue() только один раз в жизненном цикле вызывающего потока. В этот момент экземпляр MyType создается и привязывается к этому потоку. Последующие вызовы get() этим потоком снова обращаются к этому объекту.
Классический пример использования - это когда MyType - это неформатный текстовый формат/формат даты /xml.
Но такие форматы обычно не нужно выпускать или закрывать, подключения к базе данных делать, и я использую java.lang.ThreadLocal, чтобы иметь одно соединение с базой данных для каждого потока.
То, как я его вижу, java.lang.ThreadLocal почти идеально подходит для этого. Почти потому, что нет способа гарантировать закрытие ресурса, если вызывающий поток принадлежит стороннему приложению.
Мне нужны ваши мозговые сквайры: расширяя java.lang.ThreadLocal Мне удалось связать одно соединение с базой данных для каждого потока, для исключительного использования - включая потоки, которые я не могу изменить или переопределить. Мне удалось убедиться, что соединения закрываются, если поток умирает от неперехваченного исключения.
В случае нормального выхода потока сборщик мусора закрывает соединение (поскольку MyType переопределяет finalize()). На самом деле это происходит довольно быстро, но это не идеально.
Если бы у меня был свой путь, был бы другой метод в java.lang.ThreadLocal:
protected void release() throws Throwable {}
Если этот метод существовал на java.lang.ThreadLocal, вызванном JVM при любом выходе/смерти потока, то в моем собственном переопределении я мог закрыть мое соединение (и придет спаситель к Сиону).
В отсутствие такого метода я ищу другой способ подтверждения закрытия. Способ, который не будет полагаться на сборку мусора JVM.
Спасибо