[Java]Проблема с потоком

771
5
Делаю потоком свои дела, но map, почему-то, пустой о_О
Когда проверяю прям из run в потоке, то там значения есть, но когда пишу так - нет:
Код:
UpdateCheckThread thread = new UpdateCheckThread(mod);
thread.start();
String type = thread.getMap.get(key);
Сам поток:
Код:
private Map<String, String> map;

    public UpdateCheckThread(){
        super("Test Thread");
        map = Maps.newHashMap();
    }

public void run(){
        Scanner scanner = null;
        String str;
        try{
            URLConnection connection = new URL(url).openConnection();
            scanner = new Scanner(connection.getInputStream(), "UTF-8");
            while(scanner.hasNextLine()){
                str = scanner.nextLine();
                if(!str.startsWith("#") && !str.isEmpty()){
                    if(str.contains(":")){
                        String key = str.substring(0, str.indexOf(":"));
                        String value= str.substring(str.indexOf(":") + 1);
                        versions.put(key, value);
                    }
                }
            }
            for(String c : versions.values()){
                System.out.println("Значение" + " ~~~ " + c); //Вот тут проверяю
            }
        }catch(IOException e){
            
        }finally{
            if(scanner != null){
                scanner.close();
            }
        }
    }

public HashMap<String, String> getMap(){
    return map;
}
 
Вот поэтому и нельзя с ними так баловаться, с потоками. Ты создаешь поток, запускаешь его ПАРАЛЛЕЛЬНО и идешь дальше, сразу проверяешь map, а она пустая, т.к. поток ещё не выполнил метод run, потому что действует не ПОСЛЕДОВАТЕЛЬНО, а ПАРАЛЛЕЛЬНО.
Поэтому тебе надо при завершении метода run() в потоке вызывать событие в объекте, который его создал.
Или делай через while и там проверяй, завершил ли метод работу. Т.е. в потоке создаешь переменную

Код:
public boolean isFinished
и ставишь её в true в самом конце метода, а в объекте, который вызывает поток, пилишь проверку, и если переменная == true, то читаешь Map. Желательно юзать sleep, чтобы while не отжирал ЦПУ.
 
Да, точно.
Сделал так, но тогда весь майнкрафт застывает и ждет эти 10 секунд, только потом продолжает работать.
Код:
UpdateCheckThread thread = new UpdateCheckThread(mod);
thread.setDaemon(true);
thread.start();
try{
    thread.sleep(10000L);
}catch(InterruptedException e){
    e.printStackTrace();
}
String s = thread.getMap().get(key);
 
Не ну ты это.
Даешь.
Ты бы ещё на миллион поставил.
Во-первых скажи где ты это вызываешь? Где-то внутри игрового тика? Тогда храни где-нибудь инстанс потока и просто каждый тик проверяй, готов ли поток, потом вытаскивай карту, без слипа.
Если где-то в начале, в функции, которая в игре вызывается один раз, по там делай слип, но ПОМЕНЬШЕ, намного.
И вообще через событие лучше. Просто создаешь нужный метод в классе, в потоке через run его вызываешь и всё.

Код:
public void finish() {
   ...
}

public void yourMethod() {
   Thread t = new Thread() {
       public void run() {
           actions...
           finish();
       }
   };
}


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

P.S. Зачем я писал предыдущий пост, если ты всё равно сделал по-своему?
 
У меня два мода.Вот класс апдейтера:
Код:
public class UpdateChecker{

    IUpdatableMod updateMod;
    String latestVersion;

    public UpdateChecker(IUpdatableMod mod){
        updateMod = mod;
        if(AgravaineLibConfiguration.checkVersion){
            latestVersion = getLatestVersion(mod);
            MinecraftForge.EVENT_BUS.register(this);
        }
    }

    public boolean canModUpdate(){
        return latestVersion == null ? false : !latestVersion.equals(updateMod.getModVersion());
    }

    public static UpdateChecker checkForUpdates(IUpdatableMod mod){
        return new UpdateChecker(mod);
    }

    @SubscribeEvent
    public void playerLoggedIn(EntityJoinWorldEvent event){
        if(!(event.entity instanceof EntityPlayer)){
            return;
        }
        EntityPlayer player = (EntityPlayer)event.entity;
        if(!player.worldObj.isRemote){
            AgravaineLib.logger.info("Checking updates for " + updateMod.getModName() + " mod...");
            String modName = "[" + AgravaineUtilities.getRandomChatFormattingColor() + updateMod.getModName() + EnumChatFormatting.RESET + "] - ";

            if(latestVersion == null){
                player.addChatMessage(new ChatComponentText(modName + I18n.format("versionCheck.error", new Object[0])));
                AgravaineLib.logger.error("[" + updateMod.getModName() + "] - " + "No internet connection!");
                return;
            }
            if(canModUpdate()){
                //IChatComponent chatComponentUpdate = new ChatComponentText(modName + I18n.format("versionCheck.update", new Object[0]) + " " + AgravaineUtilities.getRandomChatFormattingColor() + latestVersion + EnumChatFormatting.RESET + "!");
                //chatComponentUpdate.getChatStyle().setChatClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "http://forum.mcmodding.ru/"));
                //player.addChatMessage(chatComponentUpdate);
                AgravaineLib.logger.info("Print update message for " + updateMod.getModName() + " mod.");
            }else{
                player.addChatMessage(new ChatComponentText(modName + I18n.format("versionCheck.normal", new Object[0]) + " " + AgravaineUtilities.getRandomChatFormattingColor() + updateMod.getModVersion() + EnumChatFormatting.RESET + "!"));
            }
        }
    }

    public static String getLatestVersion(IUpdatableMod mod){
        UpdateCheckThread versionChecker = new UpdateCheckThread(mod);
        versionChecker.start();
        return versionChecker.getVersions().get(MinecraftForge.MC_VERSION);
    }
В preInit какждого мода вызывается метод checkForUpdates(), то есть вызывается конструктор.
Относительно мода записываю в переменную latestVersion версию.
Потом проверяю ее и вывожу, нужен ли апдейт или нет.
 
И нахрена здесь отдельный поток вообще, если это идет при загрузке\ещё чем-то и тебе на основе результатов от этих действий надо решать грузить мод или нет?
 
Та оно виснет на пару сек без потока...
У форджа тоже отдельный поток для проверки версии.
 
Без понятия, что за ересь вы тут городите, у меня тупо достает с GitHub-а или с Pastebin-а одну строку и по ней определяет, что делать. Безо всяких потоков. Это я про updateChecker.
[merge_posts_bbcode]Добавлено: 02.06.2014 13:16:49[/merge_posts_bbcode]

И У ВСЕХ грёбанные либы. Вот будет у тебя 5 или больше модов, и во всех одинаковая система пакетов, например, тогда и пили либу, а на два мода - скопируй, да и всё.
А если не нравится, что 2 версии одного и того же класса(но в разных пакетах) будут существовать, то пихай их в 1 пакет во всех модах:
net.anti344.rcircuits.Blah
net.anti344.cr.CustomRecipes
net.anti344.lib.Lib
Так вот, пакет net.anti344.lib с одинаковым содержимым есть в джарниках обоих модов, но загрузится и будет существовать только один(ну насколько я понял, ибо Фордж не жаловался).
 
Что плохого в либах?
А если я еще мод запилить захочу, то опять копировать? Не, лучше я один раз напишу и все.
Нуок, пошлю я поток подальше и сделаю без него.
 
Dragon2488 написал(а):
И при скриншоте на пару сек виснет..
А вот скриншот можно было бы в отдельный поток сделать.
Да и вообще у можанг ущербная система скриншотов, если один пару секунд делается и весит клиент.
 
Я тебе только-что написал, что плохого(ладно, не написал, плохое то, что либа - лишний джарник, который сам по себе не делает НИЧЕГО кроме лишней потери времени), и еще - я написал, как тебе "написать один раз и не париться". Вернее написать один раз, а скопировать пару раз.
[merge_posts_bbcode]Добавлено: 02.06.2014 13:27:04[/merge_posts_bbcode]

И да, у меня скриншоты не виснут, что-то вы гоните, впервые слышу.
 
Назад
Сверху