2015-02-17 2 views
0

Предварительная информация: база данных размещена удаленно и имеет средние значения с задержкой 92 мс для подключения.Java mysql - операторы SELECT с отложенной основной нитью

У меня есть небольшая база данных MySQL, в которой хранятся данные игрока для моей игры.

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

Моя проблема заключается в том, что каждый раз, когда вход в систему игрока, моя основная тема игры задерживается на небольшое время, около 200 мс. (Каждый игровой цикл имеет 600 мс).

Я узнал, что это происходит только с операторами SELECT, все остальные запросы, такие как UPDATE, DELETE или любой запрос, который не возвращает ResultSet, просто замечательный.

Я использую C3P0 MySQL Pool, вот мои конфиги для него:

cpds.setInitialPoolSize(100); 
    cpds.setMinPoolSize(100); 
    cpds.setNumHelperThreads(200); 
    cpds.setMaxIdleTime(0); 
    cpds.setAcquireIncrement(10); 
    cpds.setMaxPoolSize(200); 
    cpds.setMaxStatements(0); 

Каждый раз, когда игрок входит в около 10 запросов выполняются, запрашивая информацию о других игроках вокруг, о своем текущем сервере чата и т. д. Эти запросы не могут быть выданы в одном заявлении, это причина нескольких потоков и соединений в c3p0, чтобы уменьшить отставание, которое работает очень хорошо.

Как я уже говорил, это происходит только с запросами SELECT, которые ожидают ResultSet.

Вопрос: Как бы я выполнил этот запрос, назначил результат переменным плеера, все, что не испортило основной поток за 200 мс?

200 мс может видеть «хорошо», но что делать, если одновременно регистрируются 50 игроков? Это просто умножает это время на создание массивной блокировки потоков.

Как я загружая игроков:

При входе в систему, это просьба:

PlayerLoader.load(username);  

Таким образом, следующий метод, который возвращает экземпляр игрока, вызывается:

public static Player load(String name) { 
    ResultSet result = null; 
    PreparedStatement ps = null; 
    Player player = new Player(); 
    Connection con = null; 
    try { 
     con = World.database().getConnection(); 
     ps =con.prepareStatement("SELECT * FROM " + PLAYER_TABLE + " WHERE username='" + name + "' LIMIT 1"); 
     result = ps.executeQuery(); 
     if (result.next()) { 
      return player.playerSaving().load(result); 
     } 
    } catch (Exception e) { 
     System.err.println("Error Loading the account: "+name); 
     e.printStackTrace(); 
    } finally { 
     try { 
      if (result != null) { 
       result.close(); 
      } 
      result = null; 
      ps.close(); 
      ps = null; 
      con.close(); 
     } catch (SQLException e) { 
     } 
    } 
    return null; 
}  

После получив ResultSet, вызывается другой метод, который присваивает переменные экземпляру проигрывателя.

Этот метод состоит из:

 player.getPlayerDefinition().getIndex(result.getShort("id")).setDisplayName(result.getString("displayName")); 
     player.getPlayerDefinition().setRights(result.getShort("rights")); 
     player.getPlayerDefinition().setPlayTime(result.getLong("playTime")); 
     player.getPlayerDefinition().setMuted(result.getInt("mute")).setMuteDuration(Long.parseLong(result.getString("muteTill"))); 
     player.getPlayerDefinition().setBanned(result.getLong("banned")); 
     player.getPlayerDefinition().setPermBanned(result.getString("permBanned").equals("true")); 
     player.getPlayerDefinition().setMemberDays2(result.getLong("member_days"));  

Это был только короткий вариант. В настоящее время он загружает все 250 строк.

Этот метод также возвращает экземпляр Player, поэтому первый метод Load вернет его. (См.: public Player load(ResultSet result)))

После этого процесса, когда экземпляр создан и готов к продолжению, игрок теперь запрашивает информацию о своем мире, чат-сервере и т. Д., И это около 6-7 небольших запросов, которые выполняются довольно быстро и , Около 2-3 из запросов - это операторы SELECT с коротким результатом.

Опять же, есть ли способ запустить этот процесс загрузки в асинхронном потоке? Если да, то как?

Спасибо.

ответ

0

Ваша проблема в том, что JDBC блокируется.

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

+0

В настоящее время я использую пять выделенных серверов. 4 из них расположены в Канаде, основной, который размещает базу данных, находится в США. Я стараюсь, чтобы удаленная производительность была хорошей, потому что я собираюсь получить больше серверов в Азии из-за пинга в этом месте. Однако загрузка базы данных должна быть быстрой, независимо от того, где находится клиент. –

1

Я решил проблему, просто создав другой выделенный поток для обработки логинов.

Как нить работает: войти

  • запросы игрока
  • запрос поставлен в очередь на исполнение, которая занимает менее 10мс в выделенном потоке.
  • Нить выполняет Runnable, не оттягивая Main Thread.