[Java lista] szalkezeles

Laszlo.Marai at nokia.com Laszlo.Marai at nokia.com
2007. Jan. 29., H, 12:52:01 CET


  Hali!

> Pár napja emlitettem egy szálkezeléssel kapcsolatos problémát.
> Sajnos azóta sem jutottam elöbb.

Mi meg valaszoltunk is. En biztosan. Es irtam, hogy szinkronizacios
problemarol van szo. Sot, mar hetekkel ezelott megirtuk tobben
is (azota nyuglodsz ugyanis ezzel a kerdessel). Arra is emlekszem,
hogy megneztem neked a Kek konyvben (mert azt hasznalod), hogy 40
oldalt kene elolvasnod, ami nem lehet tobb 3-4 oranal. Ehhez kepest
hetek ota vacakolsz.

Es legyszi probalj mar meg nem HTML levelet kuldeni.
	 
> public class Listaz extends Thread {

Egy apro tanacs: az osztaly nevek fonevek szoktak lenni.
Ha mar ragaszkodunk a magyarhoz, akkor Listazo.

> private boolean futhat;
> public Listaz() {
>	futhat = true;
>	}
	 
>	public void start() {
>	        if (t == null) {
>	            t = new Thread(this);
>	            t.setPriority(Thread.MAX_PRIORITY);
>	        }
>	        t.start();
>	    }

Ez tok rossz. (Gondolom a t a Listaz-ban van definialva, csak
lemaradt a bemasolt kodbol.) Mukodik, meg mukodhetne jol is,
csak nem erted az egeszet. A Listaz foloslegesen szarmazik a Thread-bol
(altalaban erre nincs szukseg, es nem is jo gyakorlat), mert folulcsapod
a start metodusat. Ha a Thread-bol szarmaztatsz, akkor eleg a run
metodust implementalni, az orokolt start metodus elintezi a run
futtatasat. Te azt csinalod, hogy letrehozol egy Thread objektumot
(egy Listaz-t - ugye latszik, hogy fonevnek kene lennie), amiben
letrehozol megegy Thread objektumot. Minek?

>	public void run() {
>	if (futhat) {
>	 HashMap hm = itt kap SOAP-on egy HashMap-et
>....	 
>	mystopp();
>	}

Ez teljesen rossz. Eloszor is nem olvastad el a Runnable es a Thread
dokumentaciojat. Ha elolvastad volna, akkor tudnad, hogy a run
egyszer fut le. Tehat ha te sokszor akarsz valamit megcsinalni, akkor
a run-ba egy ciklust kell rakni. A te esetedben (mivel gondolom
periodikusan akarod nyomni azt a SOAP request/feltoltest dolot,
egy while ciklust: while( futhat ) {... 

Annak, hogy egy metodus igy allitsa le a futasat, nem sok ertelme van.
Most oszinten: a mystopp-ban beallitod a futhat valtozot false-ra. Ki ellenorzi
ezt, es mikor?

>	mystopp() {
>	 futhat = false;
>	}
	 
> ez önmagában remekül feltölti a táblát...

Veletlen. Erosen baleset veszelyes kod (egyszer valakinek hozza kell
nyulnia, belenez, es letori a kezed ;) ). A helyes megoldas:

public class Listazo implements Runnable {
    private boolean running = true;

    public void run() {
        while( isRunning() ) {
            // Csinaljuk, amit kell
        }
    }


    public synchronized isRunning {
        return running;
    }

    public synchronized void stop() {
        running = false;
    }
}

Inditasa pedig:

Listazo l = new Listazo(...);
new Thread( l );

Leallitas: l.stop();

Mar ha azt akarod, hogy a Listazo folyamatosan fusson, mert ez
nem derult ki, de gondolom igy van. Hazi feladat, a synchronized
kulcsszo jelentese, es megfejteni, hogy miert van ra szukseg.

> lefutás után (netbeans profilerből is látva) a szál megáll tehát nem fut tehát sikerül megállitani
> profiler is mutatja ...

Nem allitottal meg semmit, veget ert a run metodus, ezert allt le a szal.
Ha csak egyszer akartad futtatni a feladatot (mondjuk azert,
mert GUI-bol inditottad gombnyomasra es nem akartad, hogy lefagyjon
a UI, amig dolgozol), akkor minden "if futhat" buveszkedes nelkul eleg 
a run metodust megirni.

Ne felejtsuk el, hogy a kodod ettol meg nem lesz jo, mert nem szinkronizalod
a hozzaferest a tablazathoz (vagy mihez, amibe az adatokat toltod ket szalbol
is). Amig azt nem csinalod meg, nem lesz jo a programod, akkor sem, ha sikerul
egymas utan 100x vagy 1000x a sajat gepeden jol lefuttatnod _veletlenul_.

>	CheckTask task = new CheckTask();
>	Timer t = new Timer();
>	t.schedule(task,1000,10000); //10mp-kent fut!
>	a CheckTask-ban 1 SOAP lekeres van szinten..
>	public class CheckTask extends TimerTask {
	 
>	 if (szal == null) {
>	            szal = new Thread(this);
Ez mar megint minek? Nem fut le 10 mp alatt a keres? Es ha nem, akkor azt akarod, hogy
parhuzamosan elinduljon megegy? Mert ha nem, akkor minek megegy szalat inditani?

>	            szal.setPriority(Thread.MIN_PRIORITY);
>	            szal.yield(); //hátha igy elengedi a feltöltő szálat ami eleve nagyobb prioritással bir

Nem csinal semmit a yield, mivel meg nem fut a szalad.

>	        }
>	        szal.start();
>	}

	 
>	public void run() {
>	futhat = true; //azert itt true mert a timer ezt hivja meg 10mp-ként és nem a start()-ot
>	if (futhat) {

Ennek szerinted oszinten mi ertelme van? Beallitasz egy private valtozot az N. sorban, es utana
megvizsgalod az erteket az N+1-ben. Ki valtoztatta volna meg? Es ha kivulrol (masik
szalbol) meg lehet valtoztatni, akkor miert nem sziknronizalt a hozzaferes? (De
ertelme akkor se nagyon lenne az egesznek.)

Olvasd mar el azt a nyomorult konyvet, vagy legalabb azt a szerencsetlen 40 oldalt!
Abban minden benne van (szalak, parhuzamossag, szinkronizacio). A TimerTask nincs
benne, de mindegy is, mert az nem alapkoncepcio, es ugy am block az egeszet nem erted.
Ha elolvastad, _utana_ kerdezz. Minek irjunk neked konyvet online?

  Ba'ly,
    Atleta


További információk a(z) Javalist levelezőlistáról