Как заставить поток Java закрыть подключение к локальной базе данных потока

== выполняет контрольную проверку равенства, ссылаясь на то, что 2 объекта (строки в этом случае) относятся к одному и тому же объекту в памяти.

Метод equals() будет проверять, будет ли содержимое или состояния двух объектов одинаковы.

Очевидно, что == работает быстрее, но во многих случаях может (может) давать ложные результаты, если вы просто хотите сказать, имеет ли 2 String s тот же текст.

Определенно рекомендуется использовать метод equals().

Не беспокойтесь о производительности. Некоторые способы поощрения использования String.equals():

  1. Реализация String.equals() сначала проверяет ссылочное равенство (используя ==), и если две строки одинаковы по ссылке, дальнейший расчет Выполняется!
  2. Если 2 ссылки на строки не совпадают, String.equals() будет проверять длину строк. Это также является быстрой операцией, поскольку класс String хранит длину строки, не нужно считать символы или кодовые точки. Если длины отличаются, дальнейшая проверка не выполняется, мы знаем, что они не могут быть равными.
  3. Только если мы доберемся до этого, будет фактически сопоставлено содержимое двух строк, и это будет короткий сравнение: не все символы будут сравниваться, если мы найдем несоответствующий символ (в том же положении в 2 строках), никакие другие символы не будут проверены.

Когда все сказано и даже если у нас есть гарантия, что строки являются стажерами, использование метода equals() все еще не является издержками, которые можно было бы подумать, определенно рекомендуемым способом. Если вам нужна эффективная проверка ссылок, используйте перечисления, где гарантируется спецификацией и реализацией языка, что одно и то же значение перечисления будет одним и тем же объектом (по ссылке).

13
задан Joel Shemtov 10 November 2009 в 10:19
поделиться

7 ответов

Если у вас чуткий характер, отвернитесь сейчас.

Я бы не ожидал, что это будет хорошо масштабироваться; он эффективно удваивает количество потоков в системе. Могут быть некоторые варианты использования, где это приемлемо.

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();
  }
}

Лучшая обработка ошибок и т. Д. Оставлена ​​в качестве упражнения для разработчика.

Вы также можете посмотреть на отслеживание потоков / ресурсов в ConcurrentHashMap с опросом другого потока isAlive . Но это решение - последнее средство отчаяния - объекты, вероятно, будут проверяться слишком часто или слишком редко.

Я не могу придумать ничего другого, что не связано с инструментами. АОП может работать.

Я бы предпочел объединение соединений в пул.

13
ответ дан 1 December 2019 в 20:29
поделиться

Оберните свой Runnable новым Runnable с конструкцией

try {
  wrappedRunnable.run();
} finally {
  doMandatoryStuff();
}

и позвольте THAT выполняться вместо этого.

Вы даже можете превратить его в метод, например:

  Runnable closingRunnable(Runnable wrappedRunnable) {
    return new Runnable() {
      @Override
      public void run() {
        try {
          wrappedRunnable.run();
        } finally {
          doMandatoryStuff();
        }
      }
    };
  }

, и вызвать этот метод передает исполняемый файл, который вы ищете.

Вы также можете рассмотреть возможность использования вместо него Executor. Облегчает управление исполняемыми и вызываемыми объектами.

Если вы все же используете ExecutorService, вы можете использовать его как Executor.submit (closedRunnable (normalRunnable))

Если вы знаете, что будете отключены весь ваш ExecutorService и хотите, чтобы соединения закрывались в этот момент, вы можете установить фабрику потоков, которая также закрывает «после того, как все задачи выполнены и завершение работы вызвано исполнителем», например:

6
ответ дан 1 December 2019 в 20:29
поделиться

Обычная практика JDBC заключается в том, что вы закрываете Соединение Заявление и ResultSet ) в одном и том же блоке метода. как вы его приобрели.

В коде:

Connection connection = null;

try {
    connection = getConnectionSomehow();
    // Do stuff.
} finally {
    if (connection != null) {
        try {
            connection.close();
        } catch (SQLException e) {
            ignoreOrLogItButDontThrowIt(e);
        }
    }
}

Имея это в виду, ваш вопрос заставляет меня думать, что в вашем дизайне что-то не так. Получение и закрытие таких дорогостоящих и внешних ресурсов в кратчайшие сроки убережет приложение от потенциальных утечек ресурсов и сбоев.

Если вы изначально намеревались улучшить производительность подключения, вам нужно найти соединение объединение . Вы можете использовать, например, API C3P0 . Или, если это веб-приложение, используйте встроенные средства пула соединений сервера приложений в виде DataSource .

4
ответ дан 1 December 2019 в 20:29
поделиться

Я действительно не понимаю, почему вы не используете традиционный пул соединений. Но я предполагаю, что у вас есть свои причины.

Сколько у вас свободы? Поскольку некоторые структуры DI поддерживают жизненные циклы объектов и переменные с областью видимости потоков (все они хорошо проксируются). Не могли бы вы использовать один из них? Я думаю, что Spring сделает все это из коробки, в то время как Guice потребуется сторонняя библиотека для обработки жизненных циклов и областей потоков.

Затем, какой у вас контроль над созданием переменной ThreadLocal или созданием потоки? Я предполагаю, что у вас есть полный контроль над ThreadLocal, но вы не ограничены никаким при создании потоков?

Могли бы вы использовать Aspect-ориентированное программирование для отслеживания новых Runnable или потоков, расширяющих метод run () для включения очистки? Вам также потребуется расширить ThreadLocal, чтобы он мог зарегистрироваться.

3
ответ дан 1 December 2019 в 20:29
поделиться

Вам нужно было открыть соединение один раз, поэтому вам также придется обрабатывать закрытие в том же месте. В зависимости от вашей среды потоки могут использоваться повторно, и вы не можете ожидать, что поток будет собран сборщиком мусора перед завершением работы приложения.

1
ответ дан 1 December 2019 в 20:29
поделиться

Переопределите метод get () в ThreaedLocal, чтобы он устанавливал свойство List для подкласса. Это свойство можно легко запросить, чтобы определить, был ли вызван метод get () для конкретного потока. Затем вы можете получить доступ к ThreadLocal, чтобы очистить его в этом случае.

Обновлено в ответ на комментарий

1
ответ дан 1 December 2019 в 20:29
поделиться

Я думаю, что в общем случае для этого нет хорошего решения, кроме классического: код, который получает ресурс, должен отвечать за его закрытие.

В конкретном случае, если вы вызываете потоки до такой степени, вы можете передать соединение своим методам в начале потока либо с помощью метода, который принимает настраиваемый параметр, либо с помощью некоторой формы внедрения зависимостей. Затем, поскольку у вас есть код, который обеспечивает соединение, у вас есть код, который его удаляет.

Здесь может работать внедрение зависимостей на основе аннотаций, поскольку код, который не требует соединения, не получит его и, следовательно, не будет ' его не нужно закрывать, но похоже, что ваш проект слишком далеко от проекта, чтобы модифицировать что-то подобное.

1
ответ дан 1 December 2019 в 20:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: