Хостинг серверов Minecraft playvds.com
  1. Вы находитесь в русском сообществе Bukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на русский язык плагины наших собратьев из других стран.
    Скрыть объявление

[Решено] Многопоточность / Асинхронность

Тема в разделе "Разработка плагинов для новичков", создана пользователем CoolBoy, 7 апр 2016.

Статус темы:
Закрыта.
  1. Автор темы
    CoolBoy

    CoolBoy Активный участник Пользователь

    Баллы:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Всем доброго времени суток, уважаемые форумчане.

    Честно - очень редко задавался таким вопросом: а что такое многопоточность и каким образом её можно использовать с пользой, при написании своих плагинов?

    Собственно, интересуясь этим вопросом я разворошил очень старенькие темы, тут, на рубакките, был на spigotmc.org, bukkit.org и других ресурсах связанных c java и майнкрафтом в целом. Проблема в том, что везде люди пишут разное. Кто-то пишет что нет смысла работать асинхронно, кто-то пишет, что, если это возможно, то нужно использовать асинхронность.
    Также, я так и не смог найти примеров использования многопоточности в плагинах, ну или асинхронности, как вам удобно. Из-за этого создаётся весьма сомнительное впечатление о понятии "асинхронность".

    Я хочу просто поинтересоваться/узнать, каким образом и где можно использовать асинхронные потоки и как, собственно, их использовать, если они не имеют доступа к Bukkit API?

    Также, если это возможно, хотелось бы увидеть конкретные примеры использования асинхронности, желательно - с пояснениями.
     
  2. Хостинг MineCraft
    <
  3. MrElitePro

    MrElitePro Активный участник Пользователь

    Баллы:
    46
    Имя в Minecraft:
    MrElitePro
    Асинхронность - Не совпадающий с чем-либо во времени; неодновременный, несинхронный.
     
  4. Автор темы
    CoolBoy

    CoolBoy Активный участник Пользователь

    Баллы:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Как это относится к моей теме?
     
  5. MrElitePro

    MrElitePro Активный участник Пользователь

    Баллы:
    46
    Имя в Minecraft:
    MrElitePro
    Ну это тебе должно помочь понять,что к чему
     
  6. Автор темы
    CoolBoy

    CoolBoy Активный участник Пользователь

    Баллы:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Я уже знаком с понятием, как таковым. Мне нужны примеры реализации - как правильно / как неправильно. Какой раз караю себя за выпрашивание готового, но найти на просторах интернета чего-то путного я так и не смог.
     
  7. MrElitePro

    MrElitePro Активный участник Пользователь

    Баллы:
    46
    Имя в Minecraft:
    MrElitePro
    Вот именно!!! а мне говоришь пиши,всегда лучше когда тебе дадут пример нормальный,ты разберешься в нем или тебе помогут и тогда все хорошо,а когда тебе просто текст дадут,типа на разбирай,то это не поможет тебе на практике.
     
  8. Code

    Code Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    _Gizmo
    асинхронные действия не имеют доступа к BukkitAPI -> их надо использовать, если у тебя есть какие-то довольно приличные по времени вычисления, которым не обязательно напрямую юзать апи. например, загрузить какую-нибудь приблуду из базы можно, считать что-нибудь с диска. если ты хочешь все действия игрока писать в базу, BlockBreakEvent вроде синхронный, но саму запись можно производить в асинхронном потоке, чтобы не виснул сервер.
     
  9. GoodCoder

    GoodCoder Активный участник Пользователь

    Баллы:
    76
    Имеют. Асинхронно нельзя работать с миром и всем что с ним связано. В Bukkit есть "защита от дурка", но не везде.
     
  10. Code

    Code Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    _Gizmo
    очень важное замечание, которое все кардинально меняет. забираю все свои слова обратно.
     
  11. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Вот тебе примеры:) Мой менеджер прав rscPermissions использует сразу несколько потоков:
    1. По команде или по расписанию плагину нужно перечитать данные из таблиц в БД MySQL, для этого создаётся отдельный поток, который присоединяется к этой БД (а она может быть удалённой, вообще на другой стороне планеты), считывает оттуда все данные (а их может быть тоже немало). Всё это занимает много времени (относительно времени, доступного в пределах одного такта сервера). В худшем случае, если СУБД недоступен, то соединение как минимум подвисает на timeout (несколько) секунд. Нехорошо приостанавливать весь сервер ради того, чтобы ждать timeout к недоступному серверу.
    2. Когда все данные получены, происходит их фильтрация и нормализация (строки могут быть разбиты на несколько, часть может быть откинута). Происходит сохранение в файл кеша (.json).
    3. У меня есть грубо говоря HashSet<Player>, в который игроки добавляются при движении (PlayerMoveEvent и ещё несколько других). То есть в основной поток добавлено несколько EventHandler-ов, действия которых минимальны — добавление игрока в множество. Другой параллельный поток раз в секунду (настраивается) забирает всех игроков из этого множества и опустошает его. Затем он пробегается по списку игроков и проверяет, в каких регионах находится каждый игрок (игрок ведь может быть в нескольких регионах WG). Если с момента предыдущей проверки список регионов изменился, то принимается решение, что игроку нужно пересчитать все его права (какие-то из них могут пропасть или добавиться, если игрок перешел границу влияющего на права региона). Если нужно пересчитать, то объект Player помещается в очередь на пересчёт прав.
    4. Пересчётом прав занимается ещё один параллельный поток. Он постоянно висит на получении объекта Player из очереди, и как только получает, начинает достаточно ресурсоёмкую процедуру вычисления: это проход по множеству групп и прав, выяснение того, применимы ли они к игроку, вычисление префиксов/суффиксов и т.п. В итоге на руках имеется список пар String право и boolean значение. Наконец-таки на этот момент через шедулер планируется небольшой кусок кода, который на ближайшем такте работает с Bukkit API и заменяет для игрока его набор прав на новый пересчитанный.
    Как можно заметить, при значительном объёме работы, выполняемой плагином, в потоке основного серверного цикла выполняются нерегулярные минимально необходимые кусочки кода, которые не в состоянии как-либо повлиять на TPS сервера.
     
  12. Автор темы
    CoolBoy

    CoolBoy Активный участник Пользователь

    Баллы:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Каким образом я могу сделать что-то в асинхронном потоке?
    runTaskAsynchronously?
    sheduleAsyncRepeating/DelayingTask?
    new Thread?
    Или можно запустить асинхронный поток, а в нём синхронный, в котором будет будут выполняться какие-либо действия с Bukkit API?

    Немного нубских вопросов =)
     
  13. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    • Запуск нового потока: new Thread( ... ).start();. Нет смысла использовать для этого Bukkit API, потому что это просто лишняя прослойка.
    • Выполнить код из параллельного потока в основном: Bukkit.getScheduler().runTask( ... );. Выполняет переданный ему код на ближайшем серверном тике.
    В целом, этого уже более, чем достаточно. Всё остальное это лишний сахар.

    P.S. Я тут ещё рассуждал, когда сам учился работать с параллелью в Java.
     
  14. Автор темы
    CoolBoy

    CoolBoy Активный участник Пользователь

    Баллы:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Спасибо, но я уже успел пересмотреть все ваши плагины :)[DOUBLEPOST=1460093811,1460093759][/DOUBLEPOST]
    Огромное спасибо =)
     
Статус темы:
Закрыта.

Поделиться этой страницей