Leerer Funktionsrumpf whileschleife

Hallo,
Ich hab mal eine Frage die mich doch sehr verwirrt hat.
Ich schreibe Eine gui Anwendung bei dessen Kosntruktor eine Funktion namens init() aufgerufen wird, die u.a. die Config datei mit angaben zum Benutzer ausließt. Anschließend wird die funktion createMainFrame() aufgerufen, die mir das Fenster Zeichnet.
Zur Config Datei: Ist diese noch nicht vorhanden oder leer, so wir werden die Daten eines Neuen Benutzers erfragt, dann ggf die Datei erzeugt und dann die Daten gespeichert. Am Ende setzt sie eine Globale Variable userAv auf true (siehe unten)

Nun meine Frage: um darauf zu warten dass der Nutzer erzeugt wurde, verwende ich folgende whileschleife:
Java:
while(!userAv)
{
}

Ist nicht unbedingt schön, aber erstmal die einfachste Lösung.
Nun zu meiner Frage:
Lasse ich die Schleife so wie sie ist, terminiert zwar init(), jedoch wird createMainFrame(), die direkt nach dem erstellen des Objektes aufgerufen wird, nicht ausgeführt. Das Programm hängt.
Wenn ich jedoch in die Whileschleife
Java:
System.out.println("");
einfüge, funktioniert alles wunderbar.
WARUM??

Danke schonmal
 

Daassan

Mitglied
beschäftige dich mal mit threads

deine main thraid is mit dem prüfen der usersv beschäftigt und hängt da
schreiben auf ner console is aber aufwändiger so das andere threads eingeschoben werden können

besser nutz lieber semaphoren
dann kannst den hauptthread solange sperren bis die conf datei fertig erfragt is
 
A

asdfghjl

Gast
So eine Schleife ist schon mal grundsätzlich falsch.
Sind hier mehrere Threads im Spiel? Was bedeutet "Nutzer erzeugt"?
Normalerweise hast Du doch nur einen sequentiellen Ablauf mit einer Verzweigung:
Code:
- existiert Nutzer?
ja
    - lese Nutzerdaten ein
nein
    - legen Nutzerdaten an
- mache weiter...
 
S

SlaterB

Gast
beschäftige dich mal mit threads

deine main thraid is mit dem prüfen der usersv beschäftigt und hängt da
schreiben auf ner console is aber aufwändiger so das andere threads eingeschoben werden können
deine Erklärung mit der Konsole kommt mir irgendwie mimimal geläufig/ passend vor,
aber 'beschäftige dich mal mit threads' passt dazu weniger, oder kann man genau das irgendwo nachlesen?
schwer vorzustellen

auch dass eine solche falsche Endlosschleife die GUI so deutlich blockieren kann,
schließlich wird immer zwischen Threads gewechselt..

im folgenden Programm kann die Schleife bei mir das JFrame oder dessen Verschiebung auf dem Bildschirm nicht allzu stark behindern
Java:
public class Test2 {
    public static void main(String[] args)  {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(300, 300);
        f.setVisible(true);

        while (true)
        {
            // System.out.println("");
        }
    }
}
ist die Ausgabe eingeschaltet läuft es gar noch etwas schlechter,
weil sich Eclipse im Hintergrund mit Konsole ständig aktualisieren muss ;)

mit minimierten Eclipse-Fenster allerdings besser, wird wohl stimmen

-----

grundsätzlich setzt man natürlich, falls so eine Schleife angebracht ist, Thread.sleep(30); oder so rein
-> nur noch paar Dutzend Durchläufe pro Sekunde statt Abermillionen, ein CPU-Kern auf 100% Leistung,
garantiert genug Luft für andere Threads
 
Zuletzt bearbeitet von einem Moderator:

Daassan

Mitglied
zwischen threads wird nciht zwangsläufig gewechselt insofern ein Thread nicht weiter kommt da er auf etwas wartet, dann wird gewechselt. da diese Whileschleife jedoch nichts macht außer den wert einer var auszulesen, kann er das imemr wieder machten.

ich hatte mal genau das gleiche problem
ich wollte threading betreiben udn variablen füllen
aber der hauuptthread hat seine laufzeit nicht abgegeben also kam der neen thread nie dran um rechtzeitig zu füllen

also so abwähgig ist es nicht sprech aus erfahrung hatte da auch ein paar fehler und macken drin gehabt weis nur leider nicht mehr genau um was es da ging

aber der zugrif auf ne console is doch etwas warte zeit intensiver erst dadurch kommt ein nebenthread ran

;D

ok die erste aussage is wenig informativ geb ich gern zu aber war mehr so fürs selbst studium gedacht
da bin ich doch eher von mir ausgegangen so ein hinweis reicht ja manchmal aus ^^
 
Zuletzt bearbeitet:
S

SlaterB

Gast
zwischen threads wird nciht zwangsläufig gewechselt insofern ein Thread nicht weiter kommt da er auf etwas wartet, dann wird gewechselt. da diese Whileschleife jedoch nichts macht außer den wert einer var auszulesen, kann er das imemr wieder machten.
stimmt auch wieder,
meine VM ist (wie wohl viele) nicht so streng, so dass normale Programme ohne genaue Steuerung, durchgängig arbeitende Threads, auch nebenläufig funktionieren,
das sorgt für schlechten Stil..
 
OK, hier mal ein paar codeausschnitte, vllt helfen die Ja.

Alle kommen aus der Klasse MainFrame()

Java:
public MainFrame()
	{
		userAv = false;
		init();
		System.out.println("Mainframe erfolgreich erstellt");
	}

Java:
public void init()
	{
		if(readConfig().length == 0)
		{
	  	        System.out.println("Config leer");
			init();
		}
		else
		{
                         //eigentliche init, Valriablen vorbelegen etc
                 }
         {
Java:
public String[][] readConfig()
	{
		System.out.println("Read Config");
		Reader r = new Reader("config.conf");
		Vector<String> a = r.readData(); // liest zeilenweise
		String[][] accounts = new String[a.size()][2];
		if(a.size()==0)
		{
			int option = JOptionPane.showConfirmDialog(null,"Kein Benutzer vorhanden. Neuen Benutzer Anlegen?", "Fehler", JOptionPane.WARNING_MESSAGE, JOptionPane.YES_NO_OPTION);
			if(option == JOptionPane.YES_OPTION)
			{
				System.out.println("Create user Gui wird aufgerufen!");
				createUserGui();
				while(!userAv)
				{
					System.out.print("");
				}
			}
			else
			{
				System.exit(0);
			}
		}
		else
		{
			for(int i = 0; i < a.size(); i++)
			{
				String[] ss = a.get(i).split(";");
				if(ss.length != 2)
				{
					System.err.println("Fehlerhafte Configdatei.");
				}
				else
				{
					accounts[i][0] = ss[0];
					accounts[i][1] = ss[1];
				}
			}
		}
		return accounts;
	}

createUserGUI() lasse ich mal weg. In der Funktion wird an sich nur ein Neues Fenster erzeugt wo man den Benutzer eingeben muss und den Pfad über einen JFileChooser gewählt wird. War das erfolgreich und man Klickt auf "OK" werde die Daten dort in die Configdatei geschrieben und die Variable userAv auf true gesetzt. Dies beendet dann auch die whileschleife.

Hier die Ausgabe von eclipse (mit leerer Schleife):

Read Config
Die datei unter "config.conf" konnte nicht gefunden werden!
Create user Gui wird aufgerufen!
CreateUserGui
Zu schreibende Zeile(n): "ferdi;C:\Users\Ferdi\Documents\ferdi"
Last: -1
Ordnerstruktur: config.conf
TMP-PFad: C:\Users\Ferdi\workspace\KostenrechnerGui\config.conf
Die Datei unter "C:\Users\Ferdi\workspace\KostenrechnerGui\config.conf" wurde erstellt.
zu Schreibende Zeilen: 1
User wurde erfolgreich eingetragen!


Schreibe ich nun System.out.print("") in die schleife kommt folgendes:

Read Config
Die datei unter "config.conf" konnte nicht gefunden werden!
Create user Gui wird aufgerufen!
CreateUserGui
Zu schreibende Zeile(n): "ferdi;C:\Users\Ferdi\Desktop\data\ferdi"
Last: -1
Ordnerstruktur: config.conf
TMP-PFad: C:\Users\Ferdi\workspace\KostenrechnerGui\config.conf
Die Datei unter "C:\Users\Ferdi\workspace\KostenrechnerGui\config.conf" wurde erstellt.
zu Schreibende Zeilen: 1
Config leer
User wurde erfolgreich eingetragen!
Read Config
Vor read Config
Read Config
Nach read Config
Benutzer: ferdi Pfad: C:\Users\Ferdi\Desktop\data\ferdi
init fertig
init fertig
Mainframe erfolgreich erstellt
MAInmethode create main frame
Mainframe wird gezeichnet..
 
Zuletzt bearbeitet von einem Moderator:

Daassan

Mitglied
also erstens gibt was eleganteres für config dateien
Proberties

Java:
public class AppHelper
{
        private final static URL USRWSSERVICE_WSDL_LOCATION;
        private final static Logger logger = Logger.getLogger(de.list.nutzerverwaltung.userManagementWS.NutzWSService.class.getName());
        private final static Properties properties;
        public static String newline = System.getProperty("line.separator");

    static {
        properties = new Properties();
        String pfad = System.getProperty("user.home") + File.separatorChar + "Nutzerverwaltung" + File.separatorChar + "UserMgmtConfiguration.xml";
        try {
            FileInputStream stream = new FileInputStream(pfad);
            properties.loadFromXML(stream);
            stream.close();
        } catch (Exception e) {
            //.....
            ErstelleConfigDatei(pfad);
        } 
        URL url = null;
        try {
            URL baseUrl;
            baseUrl = de.list.nutzerverwaltung.userManagementWS.NutzWSService.class.getResource(".");
            url = new URL(baseUrl, properties.getProperty("User Mgmt Service Location", "http://localhost:8080/ee_usrMgntWS/NutzWS?wsdl"));
        } catch (MalformedURLException e) {
           //....
        }
        USRWSSERVICE_WSDL_LOCATION = url;
    }

    private static void ErstelleConfigDatei(String psDateiname) {
        try {
                new File(System.getProperty("user.home") + File.separatorChar + "Nutzerverwaltung").mkdir();
                FileOutputStream stream = new FileOutputStream(psDateiname);
                properties.setProperty("User Mgmt Service Location", "http://localhost:8080/ee_usrMgntWS/NutzWS?wsdl");
                properties.storeToXML(stream, "Konfigurationsdatei zentrale Nutzerverwaltung");
            
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

ist gleich viel eleganter und einfacher zu handhaben und schon implementiert ;D

und dann wie wär es damit
du machst dein userForm was zum erstellen neuer user benutzt zu einem dialog
du machst nen readConf-aufruf mit der übergabe des frames selbst (fals die methode in nem anderen objekt ist falls nich brauchst nix übergeben)
und kannst bei dem aufruf des User-Dialogs den frame einfrieren lassen
so das erst der dialog abgearbeitet werden muss

ähnlich bei nem open/save dialog
da wird auch gewartet bis was gewählt wurde
(ich frag mich ehrlich geagt immer noch wie du zu so einem rumpf kommst o_O)

Java:
public void init()
    { 
       readconfig();
    }

public void readConfig()
{
   try{
   ...
   Proberties p = new probs...;
   p.loadFromXML(stream);
   } catch(exception ex) {    //vllt besser näher zu definieren   
      Userdialog ud = new Userdialog();
      if(ud.showDialog(this) == Abbrechen) System.exit(1);
      else
      (
         //p füllen mit dem ud eingaben
         p.savetoxml(stream);
      )
   }
}

nu hast deine xmldatei und ne porb-map mit allen eingaben

alles was das herz begeehert
 
T

tröööt

Gast
@TO
aua aua aua aua aua

das tut ja echt schon beim lesen weh ...
von leeren endlos-loops über möglich stackoverflows bis zu fehlendem grundstruktur-gedanken ist ja echt alles dabei ...

grundsätzlich ist das vorgehen schon mal komplett falsch aus dem main-thread den EDT anzustoßen und dann auf diesen warten zu wollen ...

für genau sowas gibt es events ...

ganz grob also so : dein main-thread prüft ob daten vorhanden sind ... ist dies nicht der fall wird die GUI aufgebaut (wenn man hier entsprechende klassen nutzt die blockieren geht das auch noch einfacher) und der main-thread läuft dann sauber mit nem return durch ...
der EDT kümmert sich jetzt um alles weitere ... unter anderem auch um die events die z.b. bei nem button-klick ausgelöst werden ...
das fängt man mit nem actionlistener ab ... stößt einen neuen worker-thread an um aus dem EDT raus zu kommen ... liest dann die daten aus den GUI-elementen und setzt dann da wieder ein wo der main-thread vorher ausgestiegen ist ...


setz dich mal mit dem thema "eventhandling" auseinander ... denn das dürfte deine probleme lösen ...

und dann noch : multi-dimensionale string-arrays ... vector ... alter schwede ... bau dir EIN objekt das alle infos hält anstatt so ner lustigen konstruktion ...
da fehlen ja die einfachsten grundlagen in punkto datenstruktur
 

Marco13

Top Contributor
Ohne den Code nachvollzogen zu haben: Dass aufgrund der ersten Beschreibung hier nirgends das wort [c]volatile[/c] auftauchte, wundert mich etwas...

EDIT: Aber um das noch mal zu betonen: So eine Schleife ist natürlich sowohl mit als auch ohne volatile i.a. gröbster Unfug.
 
@Daassan:
Klingt ja ganz gut, aber meine configdatei besteht nur aus: name;pfad
Deswegen denke ich reicht meine Readerfunktion vollkommen aus. Werde mir deinen Lösungsvorschlag trotzdem mal für weitere Projekte merken, Dankeschön!

@tröööt:
Mein Erfahreungen mit grafischer Programmierung sind recht beschränkt, das ist sozusagen mein erstes richtiges Projekt damit, deshalb ist es vielleicht nicht sonderlich durchdacht und dadurch unverständlich.
Nur, was ist an Vector-Objekten falsch? ich finde sie sind eine gute Methode um solche Daten zu speichern und weiter zu verarbeiten.

Ich werde nun mal mein Projekt ein bisschen überarbeiten und eure Vorschläge mit einbeziehen. Sollte ich noch weiter Probleme haben, werde ich mich wieder melden.
Vielen Dank für eure Hilfe.
 
T

tröööt

Gast
an vector selbst ist nichts falsch ... wird halt nur selten verwendet ... eine alternative wäre ArrayList ... aber performance-mäßig wärs eine mikro-optimierung ...

das stichwort "eventhandling" hab ich genannt ... und damit solltest du dich dringend befassen ... ansonsten kommst du irgendwann an den punkt das "gar nichts mehr geht" nur weil du in irgendnem loop oder call im falschen thread hängst
 

Ähnliche Java Themen


Oben