NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: Problém s vlákny(pravděpodobně synchronizace)

V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Acerik
Tvůrce
Avatar
Acerik:7.7.2016 22:03

Dobrý den, učím se vlákna tak sem si udělal bankomat. Má každou vteřinu přidat peníze na účet. Možnost zastavit vlákno a dát ho pokračovat. Ale když chci po vláknu kde je smyčka aby přidalo peníze a aktualizovalo staty. Dostanu error. Jinak vlákno bez těchto metod viz níže funguje

Zdroják vlákna

package bankomat;

import java.util.logging.Level;
import java.util.logging.Logger;

public class Vlakno extends Thread {

    Ucet ucet;
    Okno okno;
    Bankomat bankomat;
    int i = 0;
    boolean pockat = false;

    public void run() {
        while(true){
            i++;
            System.out.println(i);

            ucet.cas();
            okno.update(this);

            try {
                sleep(1000);
            } catch (InterruptedException ex) {
                Logger.getLogger(Vlakno.class.getName()).log(Level.SEVERE, null, ex);
            }
            synchronized (this) {
                while(pockat){
                    try {
                        wait();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(Vlakno.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        }
    }
}

Zdroják metody cas

public void cas(){
        penize += prijem;
    }

Zdroják metody update

public void update(Vlakno vlakno) {
        money.setText("Peníze: " + ucet.penize);
        ucetMoney.setText("Stav účtu: " + ucet.penizeUcet);
        prijem.setText("Čas: " + vlakno.i);
    }

Error

Exception in thread "Thread-0" java.lang.NullPointerException
        at bankomat.Vlakno.run(Vlakno.java:19)
Editováno 7.7.2016 22:04
Odpovědět
7.7.2016 22:03
“Every programmer is an author.”
Avatar
pocitac770
Tvůrce
Avatar
pocitac770:7.7.2016 23:06

NullPointerEx­ception, tzn. jsi někde nezinicializoal proměnnou. Jaký řádek je u tebe v IDE označen číslem 19 (je to v metodě run)? Tam najdeš chybné volání metody na objektu, který vlastně "neexistuje".

Editováno 7.7.2016 23:07
 
Nahoru Odpovědět
7.7.2016 23:06
Avatar
pocitac770
Tvůrce
Avatar
pocitac770:7.7.2016 23:12

Jenom... zde bych ti doporučil si přečíst něco o zapouzdření. Jak jsem říkal, někde nemáš zinicializovanou proměnnou. Je to způsobno tím, že objekty pravděpodobně dosazuješ z vnějšku třídy přímo, a zároveň můžeš zavolat metodu run() dříve, než bude všechno připraveno. Proto by bylo lepší si ony důležité objekty (atributy) nastavit jako privátní (ucet, okno, bankomat), vytvořit ke třídě konstruktor a doplnit je tam (předání přes parametry konstruktoru). Tím si zajistíš, že pokaždé, když si vytvoříš nové vlákno tohoto typu, tak bude vše připraveno k použití a následnému zavolání metody run()

Editováno 7.7.2016 23:13
 
Nahoru Odpovědět
7.7.2016 23:12
Avatar
Acerik
Tvůrce
Avatar
Odpovídá na pocitac770
Acerik:7.7.2016 23:59

Error je na řádek s ucet.cas(); takže do run a vlákno zapínám až jako poslední. A zkontroloval sem si pomocí vypsaní do konzole že ty proměné jsou inicializované

Nahoru Odpovědět
7.7.2016 23:59
“Every programmer is an author.”
Avatar
Hartrik
Tvůrce
Avatar
Odpovídá na Acerik
Hartrik:8.7.2016 0:59

Jiné vysvětlení, než že tam máš null, není.

BTW: měnit vlastnosti objektům ve scéně z jiného než aplikačního vlákna je zakázáno.
To platí ve Swingu i v JavaFX

Editováno 8.7.2016 0:59
 
Nahoru Odpovědět
8.7.2016 0:59
Avatar
Acerik
Tvůrce
Avatar
Odpovídá na Hartrik
Acerik:8.7.2016 1:09

Takže ten update? Jestli to chápu dobře...

Nahoru Odpovědět
8.7.2016 1:09
“Every programmer is an author.”
Avatar
Hartrik
Tvůrce
Avatar
Odpovídá na Acerik
Hartrik:8.7.2016 1:12

Jo, tam bude další chyba.

 
Nahoru Odpovědět
8.7.2016 1:12
Avatar
Acerik
Tvůrce
Avatar
Odpovídá na Hartrik
Acerik:8.7.2016 1:18

Ano, už sem vyrešil tu inicializaci že sem musel udělat rovnou

int penize = 5000;
//takhle všechny

ale tady mám další error.. Nějaká rada jak tedy aktualizovat ty staty?

Nahoru Odpovědět
8.7.2016 1:18
“Every programmer is an author.”
Avatar
Atrament
Člen IT Redactor Gang
Avatar
Odpovídá na Acerik
Atrament:8.7.2016 9:01

Tohle je špatně, nejen z hlediska vláken, ale i z hlediska objektově orientovaného návrhu aplikace. Pominu teďka to OOP a zaměřím se na vlákna.

Vlastní vlákno pomocí rozšíření Thread se pro periodicky se opakující akce obvykle nedělá, od toho je tu Timer - https://docs.oracle.com/…g/Timer.html

Vlákna pomocí rozšíření Thread se obvykle dělají, když předem nevíš jak přesně dlouho nějaká akce bude trvat, a tak chceš, aby ta akce běžela na pozadí a neblokovala například ui.

 
Nahoru Odpovědět
8.7.2016 9:01
Avatar
wgamez101
Člen
Avatar
Odpovídá na Acerik
wgamez101:8.7.2016 9:01

No musíš inicializovať aj objekty ucet, okno a bankomat v triede Vlakno, preto ti vyhodí tu chybu lebo sú null. A tie Swingové metódy by si mal volať na EDT, nejak takto.

public void update(final Vlakno vlakno) {
    SwingUtilities.invokeLater(() -> {
        money.setText("Peníze: " + ucet.penize);
        ucetMoney.setText("Stav účtu: " + ucet.penizeUcet);
        prijem.setText("Čas: " + vlakno.i);
    });
}

Mimochodom, ten kód píšem z mobilu takže tam môžu byť chyby.

Nahoru Odpovědět
8.7.2016 9:01
There are only two kinds of programming languages: those people always bitch about and those nobody uses. -- Bjarne...
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 10.