Singleton - Verständnisfrage bzgl. Variable

Ronin-Jay

Erfahrenes Mitglied
Hallo zusammen,

ich habe ein kleines Verständnisproblem bzgl Singleton und einer Variablen.

Ich habe zunächst folgende Klasse als Singleton implementiert...
Java:
package singleton;

public final class Singleton {

    /** Private Klasse, einzige Instanz von Singleton wird beim Laden von Holder erzeugt. */
    private static class Holder {
        private static final Singleton INSTANCE = new Singleton();
    }

	private int value;

    /** Konstruktor ist privat, darf nicht von außen instanziiert werden. */
    private Singleton() {
    	this.value = 12;
    }

    /** Statische Methode "getInstance()" liefert die einzige Instanz der Klasse zurück. */
    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }
    
    public void setVal(int neu){
    	this.value = neu;
    }
    
    public int getVal(){
    	return this.value;
    }
    
}

und dann 2 Testklassen mit denen ich die Variable abfragen will:
Test1
Java:
package singleton;



public class Test1 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Singleton st = Singleton.getInstance();
		
		System.out.println(st.getVal());
		st.setVal(100);
		System.out.println(st.getVal());
		
		for(int i=0;i<10;i++){
			System.out.println("..laufe..." + st);
			System.out.println(st.getVal());
			try {
				Thread.sleep(2*1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.exit(0);
		
	}

}

und Test2:
Java:
package singleton;



public class Test2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Singleton st = Singleton.getInstance();
		
		st.setVal(2);
		for(int i=0;i<10;i++){
			System.out.println("..laufe..." + st);
			System.out.println(st.getVal());
			try {
				Thread.sleep(1*1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.exit(0);
		
	}

}


Nun meine Frage - Warum erhalte ich bei Test1 für die Variable den Wert 100 (so wie ich ihn gesetzt habe), aber wenn ich mittels Test2 die Variable abfrage nur den Wert 0, bzw so wie im Source oben angegeben den Wert 2. Ich greife doch auf ein und dieselbe Instanz der Klasse zu und müßte deshalb doch über get und set die Werte der Variablen entsprechend setzen/bekommen. Synchronisiert läuft das ganze doch auch ab.... ?
 
Ich kenn mich mit Java nicht soo gut aus, aber wieso machst du es dir so umständlich mit der Holder-Klasse? Kannst du statt dieser Holder-Klasse nicht einfach eine Instanz der Singleton-Klasse als stitsche variable definieren? Ungefähr so

Code:
private static singleton INSTANCE;

und dann, getInstance() wie folgt definieren

Code:
public Singleton getInstance()
{
    if(INSTANCE==null)
    {
        INSTANCE = new Singleton();
    }
    return INSTANCE;
}

Was dein Problem angeht, du hast in beiden Testklassen eine Main-Funktion, startest du die beiden Testklassen seperat? Wenn ja dann greifst du eben nicht auf einunddieselbe Instanz zu, soweit ich weiss. Es ist glaub ich so, dass statische klassen und statische bestandteile von nichtstatischen klassen nur innerhalb eines Programms statisch sind. Wenn du dieselbe statische Klasse aus verschiedenen Programmen aufrufst, dann ist es nichtmehr dasselbe!
 
Ich kenn mich mit Java nicht soo gut aus, aber wieso machst du es dir so umständlich mit der Holder-Klasse? Kannst du statt dieser Holder-Klasse nicht einfach eine Instanz der Singleton-Klasse als stitsche variable definieren?

Das hat den Vorteil der Synchronisation: http://de.wikibooks.org/wiki/Java_Standard:_Muster_Singleton

..., startest du die beiden Testklassen seperat?
Ja.

Es ist glaub ich so, dass statische klassen und statische bestandteile von nichtstatischen klassen nur innerhalb eines Programms statisch sind. Wenn du dieselbe statische Klasse aus verschiedenen Programmen aufrufst, dann ist es nichtmehr dasselbe!
Hmm, soetwas habe ich mir schon gedacht. Aber wozu lasse ich mir dann die Instanz übergeben? Dann könnte ich es ja auch gleich ohne Singleton implementieren. Für den Aufruf einer GUI scheint es mir logisch, weil halt nur 1 Fenster offen sein soll, aber was nützt es mir, wenn ich dann zum Beispiel nicht an die Variablen dahinter kommen kann - oder mißverstehe ich da etwas? :confused:
 
An die Variablen kommst du indem du
Code:
Singleton.getInstance().getVariable1()
schreibst.
dann kannst du auf alle Variablen zugreifen. also welche al public oder mit getmethode definiert sind.
 
Wie eeemoh schon so richtig bemerkt liegt das daran das du 2 seperate Programme startest.
Wenn du die gleichen Ergebnisse haben willst, schreibe dir eine Haupklasse in der du dir dann jeweils eine Instanz der beiden testklassen erstellst.

Das was du jetzt in der mainmethoden der klasse hast kommt dann entweder in den Konstruktor oder aber in eine extra methode also z.b. so in der Art hier
Java:
package singleton;   
public class Test1 {   

private Singleton st 

public Test1() 
{    
     st = Singleton.getInstance();     
     System.out.println(st.getVal());                
     st.setVal(100);       
     System.out.println(st.getVal());  
}

package singleton;  
 
public class Test2 {   

 private Singleton st;

 public test2
  { 
       Singleton st = Singleton.getInstance();               
        st.setVal(2);       
        for(int i=0;i<10;i++){            
             System.out.println("..laufe..." + st);           
            System.out.println(st.getVal());
         }
     }
}


public class mainClass
{
    public static void main(String[] args) {
    Test1 t1 = new Test1();
    Test2 t2 = new Test2(); 
}

Habe jetzt einfach einen Teil deines Inhalts in den konstruktor er 2 Klassen gepackt, wie gesagt es gehört halt eigenltich in eine andere Methode, welche dann aufgerufen wird. Aber nur das du besser siehst warum du nicht auf deine Werte kommst. Denn du hast in beiden Programmen 1 Instanz erstellt und diese ist logischerweise nicht die gleiche. Denn Singelton bedeutet eine Instnz pro Programm oder vielleicht verständlicher pro Mainmethode.

So ich hoffe das war ausführlich genug. Wegen den methoden musst du noch mal gucken, wie gesagt ich habe einfach ein Stück in den konstruktor getan.
 
Zuletzt bearbeitet von einem Moderator:
...Denn du hast in beiden Programmen 1 Instanz erstellt und diese ist logischerweise nicht die gleiche. Denn Singelton bedeutet eine Instnz pro Programm oder vielleicht verständlicher pro Mainmethode....

Vielen Dank.
Das hatte ich nicht richtig bedacht und wurde dann etwas verwirrt, als ich mir in beiden Testklassen mal die Instanz ausgegeben habe und sie identisch war (z.B: singleton.Singleton@923e30).
 
Zurück