# Current Thread not owner



## DaKirsche (17. Dez 2008)

Moin moin,

ich bin ein blutiger Anfänger in Java und versuche gerade eine Konsolenbasierte Ausgabe über Threads zu verwirklichen.
Habe mit Java bisher eigentlich keinerlei Erfahrung.
Meine Programmierkenntnisse beschränken sich bisher auf Borland Delphi und die Paletgte der Websprachen...


Und zwar wollt ich folgendes machen:
Es werden 4 Objekte vom Typ Person erzeugt, sowie 4 Objekte von Typ Ressource.

Die Ressourcen werden den Person(en) via static-Variable zugewiesen.
Die Personen wählen nun per Zufallszahl ein Objekt aus, das Sie benutzen möchten.
Wenn es belegt ist sollen sie warten, bis es wieder frei ist und es dann benutzen.

Nach der Benutzung von 6 Ressourcen soll der Thread beendet werden.

So hier mal ein bisschen Code:

```
public class Uebung1 {

    public static void main(String[] args) {

        System.out.println("*** Es ist 09:00 Uhr morgens ***");
        System.out.println("\n*** Bestand im Fuhrpark ***");

        Ressource r1 = new Ressource("PKW");
        Ressource r2 = new Ressource("LKW");
        Ressource r3 = new Ressource("Bagger");
        Ressource r4 = new Ressource("Gabelstapler");

        System.out.println(" ");

        Person p1 = new Person("Hans");
        Person p2 = new Person("Peter");
        Person p3 = new Person("Wolfgang");
        Person p4 = new Person("Detlef");


        p1.addRessource(r1,0);
        p2.addRessource(r2,1);
        p3.addRessource(r3,2);
        p4.addRessource(r4,3);


        System.out.println("\n***Die Arbeit beginnt...***");

        p1.start();
        p2.start();
        p3.start();
        p4.start();
    }

}

class Person extends Thread{
    static int persCounter;
    static Ressource[] rs = new Ressource[4];

    private int persNr;
    private String persName;
    private int needRes = 0;
    private int worked = 0;

    public Person(String pname) {
        this.persNr = this.persCounter++;
        this.persName = pname;
        System.out.println(pname +" kommt zur Arbeit");
    }

    public  void run() {
        //Methode wird beim Aufruf des Threads gestartet
    try {
    	while(this.worked < 5) {
    		synchronized(this.getClass()) {
    		if (this.needRes <= 0) this.needRes = (int)( (Math.random() * 100)%4);
    		//System.out.println("\n\t\t\t"+this.persName+" - - - "+ (needRes));
    		if (!(this.rs[needRes].istBelegt())) {
    		//while (this.rs[needRes].istBelegt() || isInterrupted()) {Thread.currentThread().wait();};
    			this.useRes(this.rs[needRes]);
    			Thread.currentThread().notify();
    			Thread.currentThread().yield();
    		}
    		else {
    			Thread.currentThread().wait();
    		}
    	}
    	}
    	System.out.println(this.persName + " hat heute mit "+this.worked+" Maschinen gearbeitet und macht nun Feierabend!");
    	Thread.currentThread().stop();
     }
    catch (Exception e) {
    	System.out.println("!!! "+this.persName + " hat sich heute verletzt!" + e.getMessage()); //Hier wird der Fehler ausgegeben
    }
    }

    public void addRessource(Ressource r, int i) {
    	this.rs[i] = r;
    }

    public void useRes(Ressource r) {
	    	try {
	            if (!(r.istBelegt())) {
	                r.belegeRessource(this.persNr);
	                System.out.println("-OK- "+this.persName +" benutzt "+ r.getName()+"!");
	               // Thread.currentThread().notify();
	               Thread.sleep(500);
	                this.worked++;
	                this.needRes = 0;
	                System.out.println("-OK- "+this.persName +" stellt "+ r.getName()+" wieder in den Fuhrpark!");
	                r.belegeRessource(0);
	            }
	            else
	            {
	            	System.out.println("-OK- "+this.persName +" benoetigt "+ r.getName()+". "+ r.getName()+" ist belegt!");
	            	Thread.currentThread().wait();
	            }
	        }
	        catch (InterruptedException i) {
	            System.out.println("!!! "+this.persName + " ist bei der Arbeit gestorben!" + i.getMessage());
	        }
    }
}

class Ressource{
    static int resCounter;
    private int resNr;
    private String resName;
    private int belegt_von = 0;

    public Ressource(String pname) {
        this.resNr = this.resCounter++;
        this.resName = pname;
        System.out.println(pname +" steht im Fuhrpark");
    }

    public String getName() {
        return this.resName;
    }

    public void belegeRessource(int vonId) {
        this.belegt_von = vonId;
    }

    public boolean istBelegt() {
        if (this.belegt_von > 0) {
            return true;
        }
        else return false;
    }
}
```

Mein Problem hierbei ist nun, dass ich ständig die Exception erhalte "current Thread not owner".

Eine mögliche Ausgabe auf der Konsole ist folgende:


> *** Es ist 09:00 Uhr morgens ***
> 
> *** Bestand im Fuhrpark ***
> PKW steht im Fuhrpark
> ...



Kann mir jemand weiterhelfen?

MfG
DaKirsche


----------



## SlaterB (17. Dez 2008)

die Methoden notify/ wait darf man nur an den Objekten aufrufen, an denen man auch synchronized-Zugriff hat,

wenn du also 
> synchronized(this.getClass()) {
benutzt, dann musst du auch
this.getClass().wait()
aufrufen usw.

das ist was anderes als Thread.sleep(), siehe Grundlagen-Lehrbuch


----------



## DaKirsche (17. Dez 2008)

Danke...klappt^^

Jetzt habe ich aber irgendwo nen Denkfehler...in diesen Bereich geht er leider garnicht rein:

```
[...]
else 
               { 
                  System.out.println("-OK- "+this.persName +" benoetigt "+ r.getName()+". "+ r.getName()+" ist belegt!"); 
                  Thread.currentThread().wait(); 
               } 
[...]
```

Obwohl eigentlich mehrere Personen dieselbe Ressource zugeteilt bekommen....


----------



## SlaterB (17. Dez 2008)

du verwendest ja immer noch
> Thread.currentThread().wait(); 
und nicht
this.getClass().wait() 
??

wenn du dagegen
> synchronized(this.getClass()) { 
auf
synchronized(Thread.currentThread()) { 
umgebogen hast, dann war das eine eher schlechte Entscheidung,
denn jeder Thread ist ein eigenes Objekt, alle warten bei sich selber,
es findet keine gemeinsame Synchronisierung statt


----------



## DaKirsche (17. Dez 2008)

Ne...habe den Codeteil lediglich ausm 1 Post kopiert.

```
[...]
 {
	            	System.out.println("-Ooh- "+this.persName +" benoetigt "+ r.getName()+". "+ r.getName()+" ist belegt!");
	            	this.getClass().wait();
	            }
[...]
```

Sorry...

Aber zu meinem Problem jetzt geht es darum, dass folgende Ausgabe eigentlich nicht passieren sollte:


> -OK- Hans benutzt LKW!
> -OK- Peter benutzt LKW!
> -OK- Wolfgang benutzt Gabelstapler!
> -OK- Hans stellt LKW wieder in den Fuhrpark!
> -OK- Peter stellt LKW wieder in den Fuhrpark!


Da nur ein Objekt "LKW" existiert sollte eigentlich angezeigt werden:


> -OK- Hans benutzt LKW!
> -Ooh- Peter benötigt LKW. LKW ist belegt!
> -OK- Wolfgang benutzt Gabelstapler!
> -OK- Hans stellt LKW wieder in den Fuhrpark!
> -OK- Peter benutzt LKW!



Innerhalt der Klasse Ressource wird ja je Objekt eine Instanzvariable  belegt_von deklariert...

```
class Ressource{
    static int resCounter;
    private int resNr;
    private String resName;
    private int belegt_von = 0;

    public Ressource(String pname) {
        this.resNr = this.resCounter++;
        this.resName = pname;
        System.out.println(pname +" steht im Fuhrpark");
    }

 [...]

    public void belegeRessource(int vonId) {
        this.belegt_von = vonId;
    }

    public boolean istBelegt() {
        if (this.belegt_von > 0) {
            return true;
        }
        else return false;
    }
}
```

...die innerhalt der Methode Person.useRessource(); beschrieben wird (mit Personalnummer)...

```
public void useRes(Ressource r) {
	    	try {
	            if (!(r.istBelegt())) {
	                r.belegeRessource(this.persNr); //Objekt belegen
	                System.out.println("-OK- "+this.persName +" benutzt "+ r.getName()+"!");
	               Thread.yield();
	               this.getClass().notify();
                        /* Hier wird das Objekt für 500ms belegt */
                              Thread.sleep(500);
	             //  this.getClass().wait(500);
	                this.worked++;
	                this.needRes = 0;
	                System.out.println("-OK- "+this.persName +" stellt "+ r.getName()+" wieder in den Fuhrpark!");
	                r.belegeRessource(0); //Objekt wieder frei geben
	            }
	            else
	            {
	            	System.out.println("-Ooh- "+this.persName +" benoetigt "+ r.getName()+". "+ r.getName()+" ist belegt!");
	            	this.getClass().wait();
	            }
	        }
	        catch (InterruptedException i) {
	            System.out.println("!!! "+this.persName + " ist bei der Arbeit gestorben! " + i.getMessage());
	        }
    }
```

...aber obwohl die Ressource legt ist!


----------



## SlaterB (17. Dez 2008)

was ist denn nun der genaue Code?
wenn ich dem aus dem ersten Posting nehme,
dann läuft dort der synchronized-Block über die gesamte Benutzung eines Gegenstandes,

bevor also jemand etwas wieder zurückstellt kommt eh kein anderer dran,
verhindern kann man das, indem man den Monitor zwischenweise freigibt,
mit
this.getClass().wait(500);
in useRes()
statt 
Thread.sleep(500); 
geht das, falls useRes() immer noch im synchronized-Block ausgeführt wird

edit:
doch noch bisschen was gefunden, in meiner Version kann es gar nicht zur Ooh-Meldung kommen, 
da in der run()-Methode schon nach Belegung geprüft wird,
noch ein Indiz dafür, dass du inzwischen ein ganz anderes Programm hast..


und vor allem: du hast gar nicht deine Personalnummern geprüft, das wäre doch nun wirklich nicht schwer gewesen,

mit 
> static int persCounter = 0;
+
> this.persNr = this.persCounter++;
bekommt nämlich der erste Arbeiter die PersonalNr 0, damit kann man schlecht eine Ressource sperren..


----------



## DaKirsche (17. Dez 2008)

Ich hatte es auch schon überlegt mit this.getClass().wait();
Jetzt startet es zwar die anderen Threads, jedoch ändert sich an der Ausgabe nix.....leider...

Also der komplette Code, wie ich den jetzt habe ist folgender :


```
public class Uebung1 {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Automatisch erstellter Methoden-Stub
        // 500ms Nutzung
        //warten auf Freigabe
        System.out.println("*** Es ist 09:00 Uhr morgens ***");

        Ressource r1 = new Ressource("PKW");
        Ressource r2 = new Ressource("LKW");
        Ressource r3 = new Ressource("Bagger");
        Ressource r4 = new Ressource("Gabelstapler");

        Person p1 = new Person("Hans");
        Person p2 = new Person("Peter");
        Person p3 = new Person("Wolfgang");
        Person p4 = new Person("Detlef");

        System.out.println("\n*** Bestand im Fuhrpark ***");

        p1.addRessource(r1,0);
        p2.addRessource(r2,1);
        p3.addRessource(r3,2);
        p4.addRessource(r4,3);

        System.out.println("\n***Die Arbeit beginnt...***");

        p1.start();
        p2.start();
        p3.start();
        p4.start();
    }

}

class Person extends Thread{
    static int persCounter;
    static  Ressource[] rs = new Ressource[4];

    private int persNr;
    private String persName;
    private int needRes = 0;
    private int worked = 0;

    public Person(String pname) {
        this.persNr = this.persCounter++;
        this.persName = pname;
        System.out.println(pname +" kommt zur Arbeit");
    }

    public  void run() {
        //Methode wird beim Aufruf des Threads gestartet
    try {
    	while(this.worked < 5) {
    		synchronized(this.getClass()) {
    		if (this.needRes <= 0) this.needRes = (int)( (Math.random() * 100)%4);    
    		if (!(this.rs[needRes].istBelegt())) {
    			this.useRes(this.rs[needRes]);
    			this.getClass().notify();
    			Thread.yield();
    		}
    		else {
    			this.getClass().wait();
    		}
    	}
    	}
    	System.out.println(this.persName + " hat heute mit "+this.worked+" Maschinen gearbeitet und macht nun Feierabend!");
    	Thread.currentThread().stop();
     }
    catch (Exception e) {
    	System.out.println("!!! "+this.persName + " hat sich heute verletzt!" + e.getMessage());
    }
    }

    public void addRessource(Ressource r, int i) {
    	this.rs[i] = r;
    }

    public void useRes(Ressource r) {
	    	try {
	            if (!(r.istBelegt())) {
	                r.belegeRessource(this.persNr);
	                System.out.println("-OK- "+this.persName +" benutzt "+ r.getName()+"!");
	               Thread.yield();
	               this.getClass().notify();
	               this.getClass().wait(500);
	                this.worked++;
	                this.needRes = 0;
	                System.out.println("-OK- "+this.persName +" stellt "+ r.getName()+" wieder in den Fuhrpark!");
	                r.belegeRessource(0);
	            }
	            else
	            {
	            	System.out.println("-Ooh- "+this.persName +" benoetigt "+ r.getName()+". "+ r.getName()+" ist belegt!");
	            	this.getClass().wait();
	            }
	        }
	        catch (InterruptedException i) {
	            System.out.println("!!! "+this.persName + " ist bei der Arbeit gestorben!" + i.getMessage());
	        }
    }
}

class Ressource{
    static int resCounter;
    private int resNr;
    private String resName;
    private int belegt_von = 0;

    public Ressource(String pname) {
        this.resNr = this.resCounter++;
        this.resName = pname;
        System.out.println(pname +" steht im Fuhrpark");
    }

    public String getName() {
        return this.resName;
    }

    public void belegeRessource(int vonId) {
        this.belegt_von = vonId;
    }

    public boolean istBelegt() {
        if (this.belegt_von > 0) {
            return true;
        }
        else return false;
    }
}
```

und die Ausgabe ist:


> ***Die Arbeit beginnt...***
> -OK- Hans benutzt LKW!
> -OK- Peter benutzt Gabelstapler!
> -OK- Wolfgang benutzt LKW!
> ...


----------



## SlaterB (17. Dez 2008)

siehe auch mein edit oben


----------



## DaKirsche (17. Dez 2008)

Ne, das wäre echt noch in meinem Können gewesen 

Danke für die Hilfe!
Klappt jetzt...


----------

