Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Зависает! / 14 сообщений из 14, страница 1 из 1
06.10.2013, 05:58:42
    #38417939
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Зависает!
Здравствуйте. Столкнулся с непонятной проблемой. Иногда программа зависает на создании подключения(DriverManager.getConnection). Эта функция не единственная. Дело в том что ее могут вызывать сразу несколько потоков. И если в одном из вызовов зависло, то все... Остальные ждут пока поток вызвавший ее не разблокирует. В чем может быть причина?

Пример функции:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
public synchronized void setHostBusy(Session session,int busy){
		
		Connection mConnection=null;
		CallableStatement mStatement=null;
		
		try {   
			try{
				mConnection = DriverManager.getConnection(HUB_DB_URL, HUB_USER_NAME,HUB_USER_PASSWORD);
				mConnection.setAutoCommit(false);
				
				mStatement=mConnection.prepareCall("CALL SET_HOST_BUSY(?,?)");
				mStatement.setInt(1, session.host_id);
				mStatement.setInt(2, busy);
				
				mStatement.executeQuery();
				mConnection.commit();
				
				notifyUsers(session.host_id);
			}
			catch(SQLException e){
				session.disconnect();
				mConnection.rollback();
				logError(e, "setHostBusy");
			}
		}
		catch(Exception e){
			session.disconnect();
			logError(e, "setHostBusy");
		}
		finally{	
			try{
				if(mStatement!=null){mStatement.close();}
				if(mConnection!=null){mConnection.close();}
			}
			catch(SQLException e){
				logError(e, "setHostBusy");
			}
		}
	}
...
Рейтинг: 0 / 0
06.10.2013, 20:15:38
    #38418226
Мужик
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Зависает!
GorloPavelВ чем может быть причина?
Видимо в драйвере JDBC. Можно снять дамп потоков и посмотреть, где зависло.
...
Рейтинг: 0 / 0
06.10.2013, 20:38:06
    #38418245
cdtyjv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Зависает!
1) За DriverManager.getConnection() как правило скрывается пул соединений ограниченного размера. Когда другие потоки забрали все потоки, очередной поток зависнет на этом методе до тех пор, пока не появится доступного соединения.
2) У вас метод в добавок ко всему объявлен synchronized, что привносит дополнительную блокировку. Пока один поток ждет получения соединения, другие потоки не могут войти в этот метод.
3) У вас некорректно написан последний try-catch блок. Если у вас mStatement.close() бросит исключение, то mConnection.close() уже не будет вызван. Так писать нельзя.
...
Рейтинг: 0 / 0
06.10.2013, 22:31:15
    #38418302
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Зависает!
GorloPavel,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
НАЧАЛО_ПРОГРАММЫ() { 
    mConnection = DriverManager.getConnection(HUB_DB_URL, HUB_USER_NAME,HUB_USER_PASSWORD); 
}

SYNCHRONIZED_ФУНКЦИЯ() { 
   mStatement=...
   mStatement.executeQuery();
   mConnection.commit();
   mStatement.close();
 }

КОНЕЦ_ПРОГРАММЫ() { 
    mConnection.close(); 
}
...
Рейтинг: 0 / 0
06.10.2013, 22:41:23
    #38418305
cdtyjv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Зависает!
UsmanGorloPavel,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
НАЧАЛО_ПРОГРАММЫ() { 
    mConnection = DriverManager.getConnection(HUB_DB_URL, HUB_USER_NAME,HUB_USER_PASSWORD); 
}

SYNCHRONIZED_ФУНКЦИЯ() { 
   mStatement=...
   mStatement.executeQuery();
   mConnection.commit();
   mStatement.close();
 }

КОНЕЦ_ПРОГРАММЫ() { 
    mConnection.close(); 
}
Это плохая практика. Как правило, так не делают. Зачем держать соединение, если оно не используется? Корректный сценарий работы с пулом соединений: установить (или получить из пула) соединение непосредственно перед тем, как оно потребуется, закрыть (или вернуть его в пул), как только оно больше не нужно.
...
Рейтинг: 0 / 0
06.10.2013, 22:42:28
    #38418306
cdtyjv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Зависает!
cdtyjv1) За DriverManager.getConnection() как правило скрывается пул соединений ограниченного размера. Когда другие потоки забрали все потоки, очередной поток зависнет на этом методе до тех пор, пока не появится доступного соединения..Что-то я затупил и вместо DriverManager увидел DataSource За DriverManager пулов обычно нет, поэтому мой п.1 нужно проигнорировать.
...
Рейтинг: 0 / 0
06.10.2013, 22:52:31
    #38418311
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Зависает!
GorloPavelЭта функция не единственнаяcdtyjv,

Предположим, что у ТС есть функция getHostBusy(...) , которая опрашивает базу с интервалом в 2 сек. в отдельном потоке...
...
Рейтинг: 0 / 0
06.10.2013, 23:06:38
    #38418318
cdtyjv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Зависает!
UsmanПредположим, что у ТС есть функция getHostBusy(...) , которая опрашивает базу с интервалом в 2 сек. в отдельном потоке...А теперь давайте предположим, что на очередной итерации ваша соединение внезапно оказывается закрытым (сетка глюканула, СУБД перезагрузили, и т.д.). Что будете делать?
...
Рейтинг: 0 / 0
06.10.2013, 23:07:56
    #38418320
Usman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Зависает!
cdtyjvЧто будете делать?Конечно же реконнект.
...
Рейтинг: 0 / 0
06.10.2013, 23:34:01
    #38418331
cdtyjv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Зависает!
Но тогда вот это код надо менять, ибо он не учитывает реконнект:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
НАЧАЛО_ПРОГРАММЫ() { 
   mConnection = DriverManager.getConnection(HUB_DB_URL, HUB_USER_NAME,HUB_USER_PASSWORD);
}

SYNCHRONIZED_ФУНКЦИЯ() {
   mStatement=...
   mStatement.executeQuery();
   mConnection.commit();
   mStatement.close();
}

КОНЕЦ_ПРОГРАММЫ() { 
   mConnection.close();
}
...
Рейтинг: 0 / 0
07.10.2013, 06:06:29
    #38418427
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Зависает!
cdtyjvНо тогда вот это код надо менять, ибо он не учитывает реконнект:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
НАЧАЛО_ПРОГРАММЫ() { 
   mConnection = DriverManager.getConnection(HUB_DB_URL, HUB_USER_NAME,HUB_USER_PASSWORD);
}

SYNCHRONIZED_ФУНКЦИЯ() {
   mStatement=...
   mStatement.executeQuery();
   mConnection.commit();
   mStatement.close();
}

КОНЕЦ_ПРОГРАММЫ() { 
   mConnection.close();
}



А что делть если у меня несколько функций и несколько потоков которые вызывают их? Что будет если в первой функции произойдет rollback а в первой еще не выполнился запрос? mConnection же один!
...
Рейтинг: 0 / 0
07.10.2013, 08:58:13
    #38418470
cdtyjv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Зависает!
GorloPavel ,
Connection не является thread-safe, с ним нельзя работать из разных потоков.
...
Рейтинг: 0 / 0
07.10.2013, 09:10:45
    #38418476
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Зависает!
cdtyjv GorloPavel ,
Connection не является thread-safe, с ним нельзя работать из разных потоков.
Ну так у меня же он создается каждый раз? Функция synchronized, значит только один поток с ним может работать. Потом Connection закрывается. А следующий поток делает тоже самое.
...
Рейтинг: 0 / 0
07.10.2013, 09:52:22
    #38418499
cdtyjv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Зависает!
GorloPavel ,
Thread dump.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Зависает! / 14 сообщений из 14, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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