Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Одно соединение на все методы. / 25 сообщений из 29, страница 1 из 2
01.12.2013, 05:29:29
    #38484825
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
Здравствуйте. Необходимо сделать так, чтобы программа использовала только одно соединение с БД MySQL. Но проблема в том, что в программе есть класс в котором несколько методов работы с БД. В одних методах это просто чтение данных, в других запись. Но дело в том что все эти методы могут вызываться из разных потоков. Можно ли сделать так? И не будет ли проблем при вызове из synchronized блока метода с synchronized того-же объекта? Спасибо!
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
Connection mConnection;

public void method1(....){
   synchronized(mConnection){
         Что-то делаем...
   }
}

public void method2(....){
   synchronized(mConnection){
         Что-то делаем...
   }
}

public void method3(....){
   synchronized(mConnection){
         method1(...)
   }
}
...
Рейтинг: 0 / 0
01.12.2013, 06:56:44
    #38484828
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
GorloPavel,

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
public static class MySqlConnector {

    private static Connection conn;

    public static synchronized Connection getConnection(String connUrl) throws ClassNotFoundException, SQLException {
        if (conn == null || (conn != null && conn.isClosed())) {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection(connUrl);
        }
        return conn;
    }
}
...
...
...
Connection conn = MySqlConnector.getConnection("jdbc:mysql://localhost/test");
ResultSet rs = conn.createStatement().executeQuery("...");
while (rs.next()) {
    System.out.println(rs.getString(1));
}
rs.close();
...
...
Рейтинг: 0 / 0
01.12.2013, 07:53:43
    #38484831
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
UsmanGorloPavel,

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
public static class MySqlConnector {

    private static Connection conn;

    public static synchronized Connection getConnection(String connUrl) throws ClassNotFoundException, SQLException {
        if (conn == null || (conn != null && conn.isClosed())) {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection(connUrl);
        }
        return conn;
    }
}
...
...
...
Connection conn = MySqlConnector.getConnection("jdbc:mysql://localhost/test");
ResultSet rs = conn.createStatement().executeQuery("...");
while (rs.next()) {
    System.out.println(rs.getString(1));
}
rs.close();
...



Спасибо! Но чем это отличается от просто объявления Connection mConnection и последующего открытия соединения к примеру в конструкторе? Что будет если поток №1 в методе №2 будет выполнять какую-нибудь хранимую процедуру, а в потоке №3 произойдет commit на этом единственном соединении? Спасибо.
...
Рейтинг: 0 / 0
01.12.2013, 12:04:51
    #38484884
cdtyjv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
Usman, ваше решение не удовлетворяет требованиям автора. Получение соединения синхронизировано, а работа с этим соединением нет.
...
Рейтинг: 0 / 0
01.12.2013, 12:06:30
    #38484885
cdtyjv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
GorloPavelМожно ли сделать так?Можно.
GorloPavelИ не будет ли проблем при вызове из synchronized блока метода с synchronized того-же объекта?Не будет.

P.S.: Другое дело, что такая работа с СУБД как минимум не эффективна, и я с трудом могу придумать сценарии, когда такое будет требоваться.
...
Рейтинг: 0 / 0
01.12.2013, 12:10:57
    #38484887
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
GorloPavelНо чем это отличается от просто объявления Connection mConnection и последующего открытия соединения к примеру в конструкторе?В конструкторе проинициализируется переменная mConnection и откроется соединение.GorloPavelЧто будет если поток №1 в методе №2 будет выполнять какую-нибудь хранимую процедуру, а в потоке №3 произойдет commit на этом единственном соединении?mConnection - синхронизирующий объект (монитор). Синхроблок заблокирует монитор при входе одного из потоков.
Другие потоки будут ожидать пока освободится mConnection.
...
Рейтинг: 0 / 0
01.12.2013, 12:35:52
    #38484896
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
UsmanGorloPavelНо чем это отличается от просто объявления Connection mConnection и последующего открытия соединения к примеру в конструкторе?В конструкторе проинициализируется переменная mConnection и откроется соединение.GorloPavelЧто будет если поток №1 в методе №2 будет выполнять какую-нибудь хранимую процедуру, а в потоке №3 произойдет commit на этом единственном соединении?mConnection - синхронизирующий объект (монитор). Синхроблок заблокирует монитор при входе одного из потоков.
Другие потоки будут ожидать пока освободится mConnection.
Т.е пока поток #1 будет работать с методом #1 поток #2 при вызове методa #2 будет ждать пока поток #1 не закончит выполнение метода #1?
...
Рейтинг: 0 / 0
01.12.2013, 12:37:43
    #38484898
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
Т.е ваше решение будет работать так же?
...
Рейтинг: 0 / 0
01.12.2013, 12:44:47
    #38484904
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
Все равно не понимаю как в вашем случае такое возможно. Ведь getConnection вернет ссылку для потока №1 и выполнение метода продолжится дальше, а в этот момент ничего не мешает потоку №2 вызвать getConnection, получить туже ссылку и тоже начать что-то делать с БД, пока выполняется поток №1. Или я чего-то не понимаю?
...
Рейтинг: 0 / 0
01.12.2013, 13:17:04
    #38484923
cdtyjv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
GorloPavel ,
Повторюсь еще раз - решение Usman не работает так, как вы оно надо. Не работает . Логика работы с СУБД не синхронизирована. Более того, у него возможно одновременное существование нескольких разных соединений, которые не синхронизировано выполняют разные методы.
...
Рейтинг: 0 / 0
01.12.2013, 13:24:58
    #38484929
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
GorloPavel,
Ваш код не предусматривает возможности пере-создания соединения. Пусть оно в системе одно. Но если произошло аварийное отключение, то можно ведь и пересоздать.

Пример от Usman показывает идею, но при этом не является потокобезопасным.

Лучше всего взять готовый пул соединений и настроить его на одно соединение максимум. Во-первых готовый пул уже достаточно безопасен и меньше шансов накосячить с кокурентной инициализацией и прочими радостями.
Во-вторых, ваш код перестанет быть привязан к логике "единственное соединени". Если вдруг нужно, "единственно" преващается в "множественное" простой настройкой пула.
...
Рейтинг: 0 / 0
01.12.2013, 13:26:42
    #38484931
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
GorloPavelВсе равно не понимаю как в вашем случае такое возможно. Ведь getConnection вернет ссылку для потока №1 и выполнение метода продолжится дальше, а в этот момент ничего не мешает потоку №2 вызвать getConnection, получить туже ссылку и тоже начать что-то делать с БД, пока выполняется поток №1. Или я чего-то не понимаю?Так и есть. След. пример подтверждение этому:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
for (int i = 1; i <= 5; i++) {
    final String threadName = "Thread #" + i;
    new Thread(new Runnable() {
        @Override
        public void run() {
            while (true) {
                try {
                    Statement stmt = MySqlConnector.getConnection("jdbc:mysql://localhost/test").createStatement(); 
                    ResultSet rs = stmt.executeQuery("show variables");
                    while (rs.next()) {
                        System.out.println(threadName + ": " + rs.getString(1));
                    }
                    rs.close();
                    stmt.close();
                } catch (Exception e) {
                    e.printStackTrace(System.out);
                }
            }
        }
    }).start();
}

И все в пределах одного соединения.
...
Рейтинг: 0 / 0
01.12.2013, 13:38:07
    #38484936
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
В идеале, если в системе действительно много потоков и нужно синхронизировать вообще всю работу с базой, а не только получение соединений, то имеет смысл всю работу с базой выстраивать в очередь и разгребать одним единственным потоком. Например через ExecutorService и Future.
Можно попробовать через Continuation сделать. Которого на pure Java пока нет. Но есть либы, тогда не придется логику методов разрывать для огранизации очереди.
...
Рейтинг: 0 / 0
01.12.2013, 14:00:05
    #38484954
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
BlazkowiczВ идеале, если в системе действительно много потоков и нужно синхронизировать вообще всю работу с базой, а не только получение соединений, то имеет смысл всю работу с базой выстраивать в очередь и разгребать одним единственным потоком. Например через ExecutorService и Future.
Можно попробовать через Continuation сделать. Которого на pure Java пока нет. Но есть либы, тогда не придется логику методов разрывать для огранизации очереди.
Да, проще говоря мне нужно чтобы все запросы к БД были по очереди. Не асинхронно.
...
Рейтинг: 0 / 0
01.12.2013, 14:05:01
    #38484959
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
Мой вариант, который первом посте не подходит?
...
Рейтинг: 0 / 0
01.12.2013, 14:08:42
    #38484961
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
GorloPavelМой вариант, который первом посте не подходит?В method3() может произойти DeadLock:
Код: java
1.
2.
3.
4.
5.
public void method3(....){
   synchronized(mConnection){
         method1(...)
   }
}
...
Рейтинг: 0 / 0
01.12.2013, 14:14:07
    #38484962
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
UsmanGorloPavelМой вариант, который первом посте не подходит?В method3() может произойти DeadLock:
Код: java
1.
2.
3.
4.
5.
public void method3(....){
   synchronized(mConnection){
         method1(...)
   }
}


На уровне JVM или СУБД?
...
Рейтинг: 0 / 0
01.12.2013, 14:17:09
    #38484965
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
GorloPavelНа уровне JVM или СУБД?На уровне JVM
...
Рейтинг: 0 / 0
01.12.2013, 14:17:30
    #38484966
cdtyjv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
GorloPavelНа уровне JVM или СУБД?Дедлок на мониторах в JVM может произойти только в одном случае:
1) Есть больше чем один монитор
2) Захват этих нескольких мониторов из разных методов происходит неупорядоченно.

В вашем примере монитор только один, следовательно дедлок невозможен ни при каких условиях.
...
Рейтинг: 0 / 0
01.12.2013, 14:18:42
    #38484967
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
cdtyjvGorloPavelНа уровне JVM или СУБД?Дедлок на мониторах в JVM может произойти только в одном случае:
1) Есть больше чем один монитор
2) Захват этих нескольких мониторов из разных методов происходит неупорядоченно.

В вашем примере монитор только один, следовательно дедлок невозможен ни при каких условиях.
Значит мой вариант жизнеспособен?
...
Рейтинг: 0 / 0
01.12.2013, 14:35:21
    #38484979
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
UsmanGorloPavelНа уровне JVM или СУБД?На уровне JVMDeadLock'а не будет. Проверил. Сорри.
...
Рейтинг: 0 / 0
01.12.2013, 14:37:21
    #38484984
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
GorloPavel,
Откуда потоки если надо синхронно.
...
Рейтинг: 0 / 0
01.12.2013, 14:52:57
    #38484990
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
Petro123GorloPavel,
Откуда потоки если надо синхронно.
Клиентские подключения, tcp сессии. Мне нужно синхронно выполнять некоторые вещи.
...
Рейтинг: 0 / 0
01.12.2013, 15:03:24
    #38484995
cdtyjv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
GorloPavelЗначит мой вариант жизнеспособен?Жизнеспособен за исключением одного но. Он жизнеспособен, если вы всегда работаете с одним и тем же коннекшном. Если же, например, у вас он сдох, и надо пересоздать новый, то как раз здесь вы можете получить букет проблем с дедлоками и прочей многопоточной хренью. Как уже сказал Blazkowicz, надо смотреть в сторону пула соединений, который снимет вас всю головную боль касательно многопоточности.
...
Рейтинг: 0 / 0
01.12.2013, 15:06:21
    #38484999
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одно соединение на все методы.
GorloPavel, задание странное. Даже самые лютые и суровые DBA-шники позволяют 2-4 физ. соединения создать.
Вам с пулом на 1 соедиенние надо понимать что могут быть состояния когда с вашей стороны уже активности
нет а пул всё еще не доступен.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Одно соединение на все методы. / 25 сообщений из 29, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]