[ Texas Instruments @ 16.06.2010. 02:23 ] @
Kako da realizujem da mi se izračunavanje neke metode iz klase koja bi imala i rekurzivne pozive, prekine nakon određenog vremena i vrati do tog trenutka izračunatu vrednost?
Metodi bi se prosledio jedan long kao argument koliko maksimalno vremena se dozvoljava za računanje.
[ grizzly @ 16.06.2010. 09:29 ] @
Pa prosledi jos jedan long koji je pocetno vreme u milisekundama i proveravaj u svakom pozivu koliko je proslo kad prodje vise pocni da vracas vrednost...
[ Texas Instruments @ 16.06.2010. 12:04 ] @
Nisam naznačio da tu metodu ustvari dobijam da implementiram iz nekog interfejsa i ne mogu da je menjam, tako da ima samo jedan long argument i još neke druge. :(
[ Tulex @ 17.06.2010. 07:21 ] @
Prvo sto mi pada na pamet jeste poseban thread i poziv te metode u tom thread-u.
Rezultat izracunate vrednosti smestaj u neku static promenljivu koja bi trebala biti i sinchronized.

U drugom, parent thread-u meris vreme i kad istekne samo ubijes ovaj thread sto pokrece tvoju metodu.
[ Texas Instruments @ 17.06.2010. 12:22 ] @
Tako mi je nešto i savetovano, ali nisam siguran kako bi to trebalo da se uradi. Je li bi mogao da napišeš taj deo sa nitima kako bi izgledao, a da recimo metoda samo upisuje u nekoj petlji broj u neku static promenljivu, čisto radi simulacije tog izračunavanja.
[ Tulex @ 17.06.2010. 12:52 ] @
Evo nesto na brzinu.
Prvo ti treba tvoja klasa npr. MyThread koja ce nasledjivati klasu Thread
Code:

public class MyThread extends Thread {
    
    public static int value = 0;
    
    public void run() {
        
        // Ovde pozoves tu metodu koja ce nesto da racuna
        
        // Ovde takodje mozes i uzimati rezultat te metode i upisivati u neku
        // staticki atribut...
        // npr. ova klasa moze da ima neki staticki atribut value
        
        
    }

}


U ovoj metodi run napises sve sta hoces da ti se izvrsava dok je taj thread ziv.

Sledeci korak je da negde u svom kodu kreiras instancu ove svoje klase MyThread i pokrenes start();
Code:

     MyThread t = new MyThread ();
     t.setDaemon(true);
     t.start();

I onda cekas da to vreme koje si odredio istekne.. i zatim ubijes taj thread.

Ubijanje thread-a je zeznut deo. Postoje metode stop(), suspend(), destroy() ali se ne preporucuju.. nisu napravljene u startu kako treba.
Ali najcesce se desi da nemas drugog resenja.
Dakle pozoves sledece
Code:

      t.suspend();
      t.stop();

i zatim mozes da procitas vrednost koju si unosio u staticki atribut value
Code:

int val = MyThread.value;


Ovo je daleko od idealnog, ali ce ti uraditi posao.


[ bantu @ 17.06.2010. 13:40 ] @
Mozda moze ovako. Na brzinu sam to sklepao treba uzeti sa rezervom.

Code:

import java.util.Timer;

public class MainClass {
    
    private boolean running = true;

    public int racunaj() {
        int count = 0;
        TajmerTask task = new TajmerTask(this);
        Timer t = new Timer();        
        t.schedule(task, 1000);        
        while (isActive()) {
            count++;
        }
                 t.cancel();
        return count;
    }

    public synchronized boolean isActive() {
        return running;
    }

    public synchronized void setState(boolean running) {
        this.running = running;
    }
    
    /**
     * @param args
     */
    public static void main(String[] args) {
        
        MainClass m = new MainClass();    
        System.out.println(m.racunaj());
        

    }

}


Code:

import java.util.TimerTask;



public class TajmerTask extends TimerTask{
    
    private MainClass m;
    
    public TajmerTask(MainClass m) {
        this.m = m;
    }
        

    @Override
    public void run() {
        m.setState(false);        
    }

}


[Ovu poruku je menjao bantu dana 17.06.2010. u 14:55 GMT+1]
[ MMX @ 19.06.2010. 10:14 ] @
Puno bolje rešenje je ovo što je bantu preporučio. Nikada ne treba da ubijaš nit pomoću gore navedenih metoda. Uvek se vrti u nekoj petlji i setuj vrednost variable na false kada želiš da izađeš iz nje, a nit da se završi.
[ Tulex @ 19.06.2010. 10:35 ] @
Slazem se da je uvek bolja while petlja nego ubiti neki thread.
Problem je sto cesto nisi u mogucnosti napraviti tako nesto.
Inace cisto da bi videli da je u pitanju ista stvar evo ispravke MyThread klase
Code:

public class MyThread extends Thread {
    
    public static int value = 0;
    public boolean running = false;
    
    public void run() {
        
        while(running) {
          // U ovoj while petlji iznova i iznova pozivas tu svoju metodu 
          // dok god iz parent thread-a ne kazes da je running = false

        }
        
        
    }

}


Problem o kom sam govorio je kad jednom udjes u tu metodu i vise nisi u stanju da izadjes iz nje dok se thread ne ubije.
Znaci nema while petlje, nema iteracije.. udjes u metodu i cekas da se proces zavrsi ili da se thread ubije.
Mnogo puta mi se bas to desilo kad smo imali metodu koja se mogla zaglupiti i thread ne izlazi iz nje.
Jedino resenje je ubiti thread spolja nakon nekog vremena.
[ MMX @ 19.06.2010. 18:48 ] @
Grešiš. Metoda se "zaglupi" zato što posle nekog vremena JVM kešira vrednost promenljive running, pa umesto false može se desiti da prikaže (uzme) vrednost true. Problem rešavaš pomoću ključne reči volatile koja sprečava keširanje. Deklaracija promenljive bi trebalo da izgleda ovako:

public volatile boolean running = false;
[ Texas Instruments @ 19.06.2010. 19:33 ] @
Ljudi, hvala na pomoći. Sviđa mi se ovo rešenje koje je ponudio bantu, samo imam problem sada što se ta nit izvrši za jedan poziv i prilikom sledećeg poziva ne računa se ponovo.
Kako da izmenim da se ta MainClass kreira jednom, a da za svaki poziv
Code:
m.racunaj(long timeToRun);
izvršava toliko vremena koliko je potrebno.
[ Tulex @ 19.06.2010. 20:10 ] @
@MMX nisi me razumeo. Nema while petlje, nema promenljive running...

imas poseban thread i u njenoj run metodi imas poziv neke metode iz neke externe biblioteke nad kojom ti nemas nikakvu kontrolu.
Desava se da ta metoda zaglupi iz samo njoj poznatih razloga ili izvrsavanje predugo traje.
Da tvoja aplikacija ne bi cekala doveka da se to izvrsi jedino sto mozes uraditi jeste ubiti thread i obavestiti korisnika da akcija nije uspela.
Imao sam u par navrata takvu situaciju.
Inace, u pravu si sto se tice kesiranja ali to je druga prica i nema veze sa problemom koji sam ja gore naveo.
[ MMX @ 20.06.2010. 06:59 ] @
Aham, ok. Onda se nismo dobro razumeli. :)