OZ 2011/1-2

M T 39 ORGANIZACIJA ZNANJA 2011, LETN. 16, ZV. 1 – 2 • Razredi Tu je vključena prevedena koda v bajtih (datoteke tipa .class ). Ko se prevedena koda pri zagonu naloži, se kreirajo metapodatkovne strukture, ki jih uporablja javanski paket java.lang.reflect . Tudi ti zasedejo določeno količino pomnilnika. Vse konstante programa se naložijo v ta pomnilnik. In nazadnje še prevajalnik JIT doda svojo nativno prevedeno kodo. • Niti Niti uporabljajo določene sistemske vire, toda prednosti njihove uporabe so take, da se s porabo virov ne obremenjujemo. • Nativne podatkovne strukture Java uporablja nativne knjižnice operacijskega sistema . AWT , ki na primer uporablja ogromno nativnih podatkovnih struktur. • Nativna koda Java uporablja sistemske knjižnice DLL za dostop do mreže, diskov in drugih sistemskih virov. Razredi se naložijo v pomnilnik, ko jih prvič potrebujemo oz. se na njih sklicujemo. Dejansko pa jih včasih sploh ne potrebujemo, pa se vseeno inicializirajo in trošijo sistemske vire: public static Translator getTranslator(String fileType) { if (fileType.equals("doc")) return new WordTranslator(); else if (fileType.equals("html")) return new HTMLTranslator(); ... Ne glede na tip dokumenta se v prejšnjem primeru naložijo vsi razredi. Ta problem lahko zaobidemo z uporabo paketa java.lang.reflect : public static Translator getTranslator(String fileType) { if (fileType.equals("doc")) { return (Translator) Class. forName("WordTranslator"). newInstance(); } else if (fileType.equals("html")) { return (Translator) Class. forName("HTMLTranslator"). newInstance(); ... Tu se dejansko naloži le tisti razred, ki ga res potrebujemo. Količino naloženih razredov lahko zmanjšamo tudi tako, da zaženemo več aplikacij znotraj istega navideznega stroja ( JVM ), kar pa je po našem mnenju zelo redka uporaba: Class clazz = Class.forName(className); Class[] argsTypes = new {String[].class}; Object[] args = {new String[0]}; Method method = clazz.getMethod("main", argsTypes); method.invoke(clazz, args); Vsako tako aplikacijo je seveda treba zagnati v svoji niti. Odziven grafi~ni vmesnik Za prijetno delo je zelo pomemben odziven uporabniški vmesnik, saj dajejo že zakasnitve nad 50 milisekund občutek počasnega vmesnika. Trajajoče operacije je treba izvajati v ločenih nitih, saj tako zakrijemo slabo odzivnost. Lahko pa uporabniku prikažemo potek izvajanja operacije s ProgressBar , s čimer ga tudi nekoliko pomirimo. Pri delu z nitmi znotraj grafičnega vmesnika je treba biti zelo pazljiv, saj se lahko pojavijo nezaželene napake pri prikazu. Celoten grafični vmesnik se v javi izvaja znotraj ene same niti event-dispatching thread ( EDT ). S tem je zagotovljen lažji nadzor nad risanjem vmesnika in pravilnim zaporedjem izvajanja proženih dogodkov ( event-handling ). Proženje dogodkov oz. risanje izven niti EDT lahko povzroči nepravilno risanje in osveževanje grafičnih elementov aplikacije. Privede pa lahko tudi do nepravilnega zaporedja sproženih dogodkov. Delo z vmesnikom v drugih nitih moramo izvesti z uporabo metod javax.swing. SwingUtilities.invokeLater() in .invokeAndWait() , ki poiščeta nit EDT in zaženeta želeno operacijo znotraj te niti. Prva metoda se izvede, ko ima sistem čas, medtem ko se druga metoda izvede takoj. Primer dela z grafičnim vmesnikom znotraj drugih niti: Runnable doWork = new Runnable() { public void run() { // do some GUI work } }; SwingUtilities.invokeLater(doWork); Pri morebitnih problemih z osveževanjem oken je najlažje preveriti, ali smo res v niti EDT z uporabo metode SwingUtilities.isEventDispatchThread() . Ker je delo z nitmi v grafičnem vmesniku zahtevno, so v Javi vključili poseben vmesnik javax.swing.SwingWorker , ki zelo olajša delo z nitmi. Primer uporabe SwingWorker : final JLabel label; class MeaningOfLifeFinder extends SwingWorker<int, Object> { @Override public int doInBackground() { for (int i=1; i<42; i++) { publish(i); POROČILO

RkJQdWJsaXNoZXIy MTAxMzI5