Probleme mit einem einfachen Thread

AKST

Erfahrenes Mitglied
Hallo Leute,

ich habe diesen einfachen Thread geschrieben:

Code:
public class ZaehlThread extends Thread{
	
	public void run(){
      zaehlen();
			
	}
	
	synchronized void zaehlen(){
		for(int i=0; i<= 200; i++)
			System.out.println(i);	
	}

}

und rufe diesen so auf:
Code:
public class FirstThread {

	public static void main(String[] args) {
		
		ZaehlThread zahlen = new ZaehlThread();
		
		
		zahlen.start();
		
		zahlen.start();
		
	}
}

Wenn ich vom Objekt "zahlen" die Startmethode (start) nur einmal aufrufen lasse, dann gibt es keine Fehlermeldung, warum aber wenn ich das zweimal tue?
Ich möchte die Methode "zaehlen" zweimal vom gleichen Objekt nebeneinander starten. Geht das, wenn ja wie?
 
Du hast folgende Alternative:
indem du dir zwei Objekte von deinem ZaehlThread holst und
dann u. U. eine static Klassenmember einführst die du dann hochzählen kannst. Sollte in deinem Fall die gleiche Wirkung erzielen.
 
Zuletzt bearbeitet:
So in etwa:

Code:
/*
 * Created on 04.07.2004
 *
 * TODO 
 */

/**
 * @author Administrator TODO Describe what the class is used for
 */
public class ThreadDemo {

    public static void main(String[] args) {
        ThreadDemo demo = new ThreadDemo();
        Thread cTA = demo.new CountThread("CountThreadA");
        Thread cTB = demo.new CountThread("countThreadB");

        cTA.start();
        cTB.start();
    }

    class CountThread extends Thread {
        public CountThread(String name) {
            super(name);
        }

        public void run() {
            try {
                for (int i = 0; i < 200; i++) {
                    System.out.println(this.getName() + ": " + i);
                    Thread.sleep(100L);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Gruß tom
 
Code:
/*
 * Created on 04.07.2004
 *
 * TODO 
 */

/**
 * @author Administrator TODO Describe what the class is used for
 */
public class ThreadDemo {

    public static void main(String[] args) {
        ThreadDemo demo = new ThreadDemo();
        Thread cTA = demo.new CountThread("CountThreadA");
        Thread cTB = demo.new CountThread("countThreadB");

        cTA.start();
        cTB.start();
    }

    class CountThread extends Thread {
        public CountThread(String name) {
            super(name);
        }

        public void run() {
            try {
                for (int i = 0; i < 200; i++) {
                    System.out.println(this.getName() + ": " + i);
                    Thread.sleep(100L);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

oder Alternativ: (je nach Anwendungsfall

Code:
/*
 * Created on 04.07.2004
 *
 * TODO 
 */

/**
 * @author Administrator TODO Describe what the class is used for
 */
public class ThreadDemo {

    private static int zaehler = 0;
    public static void main(String[] args) {
        ThreadDemo demo = new ThreadDemo();
        Thread cTA = demo.new CountThread("CountThreadA");
        Thread cTB = demo.new CountThread("countThreadB");

        cTA.start();
        cTB.start();
    }

    class CountThread extends Thread {
        
        public CountThread(String name) {
            super(name);
        }

        public void run() {
            try {
                 synchronized(getClass()){
                         for (; zaehler < 200; zaehler++) {
                                     System.out.println(this.getName() + ": " + zaehler);
                              
                         }
                  }
                   Thread.sleep(100L);
                  
                }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

@tom sorry for modification
 
Zuletzt bearbeitet:
Ihr habt beide Recht,

ich habe vergessen zu sagen worum es mir wirklich geht:

Ich möchte die Wirkung von "synchronized" ausprobieren. In meinem Buch steht, dass sich "synchronized" aber nur auf mehrere Aufrufe für das gleiche Objekt bezieht.
Es ist nämlich so, dass wenn ich zwei verschiedene Threads starte, dann werden die Zahlen der obigen Schleife gemischt ausgegeben (also jeweils abwechselnd von zwei Threads).
Code:
ZaehlThread zahlen = new ZaehlThread();
ZaehlThread zahlen2 = new ZaehlThread();
		
zahlen.start();
zahlen2.start();

Jetzt möchte ich, dass durch synchronized diese Methode nur von einem Thread gleichzeitig benutzt werden darf.
Code:
public class ZaehlThread extends Thread{
	
	public void run(){
           zaehlen();
			
	}
	
	synchronized void zaehlen(){
		for(int i=0; i<= 200; i++)
			System.out.println(i);	
	}

}
Die Zahlenreihen werden aber trotz synchronized gemischt ausgegeben.

Wie kann ich also die Methode "zaehlen" zweimal gleichzeitig vom gleichen Threadobjekt abarbeiten lassen? Ich möchte einmal ohne synchronized ausprobieren, dass die Zahlen wirklich gemischt ausgegeben werden, und einmal mit synchronized, dass diese Methode wirklich nur einen Zugriff erlaubt.
 
Zuletzt bearbeitet:
Also zur Erklärung:
Das synchronized is die Realisierung des Monitorings in Java,
d.h. Das wenn ein Thread in den Monitor ( kritischer Abschnitt) eintritt er den
diesen Bereich sperrt. Er signalisiert somit anderen Threads, das er jetzt dran ist und die anderen Threads warten müssen bis er fertig mit der Abarbeitung ist (den Monitor verlässt). Wenn er aus dem Monitor wieder heraustritt wird der Bereich für den nächsten Thread freigegeben.
Das macht insbesodere Sinn wenn auf gemeinsame Resourcen zugegriffen wird, damit
keine unbeabsichtigten Zugriffe auf Variablen auftreten und es somit zu Kollisionen
kommt.

Dein Vorhaben, das ein ThreadObjekt gleichzeitig die Methode zaehlen 2 mal abarbeitet,
ist nicht möglich da das der Natur(Definition) eines Threads widerspricht(siehe Zitat von Tom).

Ich hoffe das hilft Dir weiter...

Gruß

RedWing
 
Hallo!

Das gleiche Phänomen hab ich bei mir auch ... auch mit dem Beispiel aus dem Handbuch der Javaprogrammierung von Seite 479 kommen bei mir alle Zahlen nach einander in der richtigen Reihenfolge...

Na ja hier mal ein anderes Beispiel von mir:

Code:
/*
 * Created on 04.07.2004
 *
 * TODO 
 */

/**
 * @author Administrator TODO Describe what the class is used for
 */
public class ThreadDemo extends Thread {

    private static String myName = "";

    public static void main(String[] args) {
        Thread t1 = new ThreadDemo();
        Thread t2 = new ThreadDemo();

        t1.start();
        t2.start();
    }

    public void run() {
        while (true) {
                doIt();
        }
    }

    /**
     * 
     * TODO Describe what the Method does
     */
    private void doIt() {
        //synchronized (getClass()) {

            setMyName();

            try {
                sleep(20L + (long) Math.abs(50 * Math.random()));
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            printHallo();
         //}
    }

    /**
     * 
     * TODO Describe what the Method does
     */
    public void setMyName() {
        myName = getName();
    }

    public void printHallo() {
        String str = "Ich bin : " + myName;
        System.out.println(str);
        System.out.println("In wirklichkeit bin ich aber : " + this.getName());
        System.out.println();

    }
}

Zum testen der Auswirkungen eines synchronized Blocks einach mal die Kommentarzeichen von synchronized und der schließenden Klammer entfernen.

Gruß Tom
 
Jupp danke dir, ich probiers mal aus...

P.S. aber dass bei meinem letzten Beispiel mit synchronized die Zahlen eigentlich nicht gemischt, sondern nacheinander ausgegeben werden sollten ist doch richtig, oder?
 
Sooo,

das Problem ist folgendes:

Das Abschließen einer Methode duch synchronized bezieht sich nicht auf die Methode an sich sondern auf das Objekt. Deshalb hat es in meinem Beispiel auch nicht funktioniert, da ich zwei Thread-Objekte habe die jeweils eine eigene "zaehlen"-Methode haben. Das meinte der Autor des besagten Buches auch ("Java ist auch eine Insel"- kann ich nur empfehlen).
Um die Funktionsweise von synchronized an meinem letzten Beispiel zu verdeutlichen, habe ich folgenden Code, bei dem ein unterschiedliches Ergebnis entsteht, je nach dem ob synchronized weggelassen wird oder nicht, geschrieben.

Code:
public class ZaehlThread extends Thread{
	
	FirstThread objneu = new FirstThread();
	
	public ZaehlThread(FirstThread obj ) {
           objneu=obj;    	
	}
	public void run(){
           objneu.zaehlen();    
			
	}
	
}

public class FirstThread {

	synchronized void zaehlen(){
		for(int i=0; i<= 200; i++)
			System.out.println(i);	
	}
	
	public static void main(String[] args) {
		
		FirstThread erster = new FirstThread();
		
		ZaehlThread zahlen = new ZaehlThread(erster);
		ZaehlThread zahlen2 = new ZaehlThread(erster);
		
        
		zahlen.start();
		zahlen2.start();
		
	}
}

Man sieht, dass zwei Thread-Objekte das gleiche Objekt (erster ) bearbeiten wollen. Synchronized verhindert einen gleichzeitigen Zugriff auf die Methode "zaehlen".

Gruß
 
Zuletzt bearbeitet:
Zurück