Войти или зарегистрироваться
  • Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.

[Решено] Странный while в отдельном потоке

sashabelii

Старожил
Пользователь
Баллы
123
Имя в Minecraft
sashabelii
Доброго.

Есть отдельный поток, который хранит в себе мир, ждет пока тики побегут после массивной операции в основном потоке, потом отсчитывает некоторое их количество и продолжает работу:
Код:
    @Override
    public void run() {
    ...
            long timeFrom = world.getFullTime();
            while(world.getFullTime() < timeFrom + pushTimeout) {
                System.out.println();
            }
    ...
}
Я до конца не понимаю, что на это влияет, но цикл зависает/зацикливается, если не вызывать внутри него методы System.out.println();/поток.sleep(N);(возможно еще какие-то подойдут).
Почему так?
 
1) Шедуллеры - это не потоки, это просто задания, который выполняются.
2) Есть вероятность того, что ты делаешь deadlock тем, что работаешь с миром не из основного потока. Нужно ознакомиться с конкуренцией в java.
 
Весь этот код выполняется во время одного тика. Условие в цикле становится ложным только при отрицательном pushTimeout.
 
Весь этот код выполняется во время одного тика. Условие в цикле становится ложным только при отрицательном pushTimeout.

Извиняюсь, не ясно выразился. Будет понятнее, если я покажу весь код:
// Все это дело работает в отдельном потоке, это не запланированная задача.
Код:
public class ChunkCalculator extends Thread {
...
    @Override
    public void run() {
        EditSession editSession = WorldCleaner.worldEdit.getWorldEdit().getEditSessionFactory().getEditSession(BukkitUtil.getLocalWorld(world), 0);
        ChunkStore chunkStore = null;
        try {
            chunkStore = WorldCleaner.worldEdit.getLocalConfiguration().snapshotRepo.getSnapshot(world.getName() + File.separator + Config.getSnapshotName(world.getName())).getChunkStore();
        } catch (IOException | InvalidSnapshotException | DataException e) {
            e.printStackTrace();
        }

        calculateChunksInRadius(radiusInChunks);

        WorldCleaner.log.info("Calculating chunks for world: "+ world.getName() + " is done. To regenerate: " + chunks.size() + " chunks. ");

        if (isFromSnapshot) {
            WorldCleaner.log.info("Starts world restoring from snapshot: " + Config.getSnapshotName(world.getName()));
        } else {
            WorldCleaner.log.info("Starts world regenerating...");
        }

        while(!chunks.isEmpty() && isRunning) {  // Пушим

            Queue<Vector2D> currentChunks = chunks.getLast();
            if (isFromSnapshot) {
                worker = new ChunkRestorer(world, currentChunks, editSession, chunkStore);
            } else {
                worker = new ChunkRegenerator(world, currentChunks);
            }
            Bukkit.getServer().getScheduler().runTask(WorldCleaner.plugin, worker);
            chunks.removeLast();

            // Ждем тики и соответсвенно завершение работы с пушем чанков(тики в этот момент стоят)
            long timeFrom = world.getFullTime();
            while(world.getFullTime() < timeFrom + pushTimeout) {
                System.out.println();
            }
            checkMemoryLevel();
        }
        WorldCleaner.regeneratorsMng.continueRegenerating();
    }
...

2) Есть вероятность того, что ты делаешь deadlock тем, что работаешь с миром не из основного потока. Нужно ознакомиться с конкуренцией в java.
Работаю из основного. Я почти уверен, что getFullTime потоко-безопасный метод.

Главный вопрос: Что такого делает System.out.println();, что цикл работает как нужно?
 
Вывод строки тоже время занимает.
Т.е. while не может до какого-то момента делать "ничего"?
Загуглил, понял. while судя по всему занимает все процессорное время, или что-то в этом духе. Все свелось к ожиданию по времени во имя пропуска постоянных пустых циклов, которые делают "ничего".
Код:
            long timeFrom = world.getFullTime();
            while(world.getFullTime() < timeFrom + pushTimeout) {
                try {
                    sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
Такие дела.
 
Т.е. while не может до какого-то момента делать "ничего"?
Загуглил, понял. while судя по всему занимает все процессорное время, или что-то в этом духе. Все свелось к ожиданию по времени во имя пропуска постоянных пустых циклов, которые делают "ничего".
Код:
            long timeFrom = world.getFullTime();
            while(world.getFullTime() < timeFrom + pushTimeout) {
                try {
                    sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
Такие дела.
Когда-то накатал такое чтобы шедулить таск и ожидать оконачания его выполнения.
https://github.com/Shevchik/AutoSaveWorld/blob/devel/src/autosaveworld/utils/SchedulerUtils.java#L43
 

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

Назад
Верх