Prioritäten bei SwingWorker / Threads

Maxi92

Aktives Mitglied
hei leute!

ich hab folgendes Problem und hoffe Ihr versteht meine Erklärung da des zum erklärn recht komplex is...

ich hab ne Klasse > DefaultClient in der die Methode > sendAndReceiveLine drinnen is
sendAndReceiveLine wird dafür verwendet um eine Socketverbindung mit einer SPS herzustellen und einen beliebigen String zu senden und gleichzeitig einen String zu empfangen.

weiters habe ich eine Klasse > ManuellGUI wo ich mit 10 verschiedenen Kanonen schiessen kann
wenn ich jetzt zb: bei Kanone 1 auf den Button Feuern drücke wird mittels > sendAndReceiveLine ein String gesendet damit die SPS weiß, dass sie den jeweiligen Ausgang setzen muss. Gleichzeitig kommt ein String zurück! entweder ERR, OFF, BSY oder die Geschwindigkeit

zusätzlich habe ich eine Klasse > MesswertlisteGUI in der mit F5 ein SwingWorker gestartet wird der alle Sekunden ebenfalls die Methode > sendAndReceiveLine aufruft, um wenn ein neuer Geschwindigkeitswert vorhanden ist, ein Objekt Kanone zu erstellen und das mit publish() und process() in eine JList zu schreiben!

mein Problem ist nun wenn ich in der Klasse > ManuellGUI auf den Button Feuern drücke und zufällig genau dann die Methode > sendAndReceiveLine aufgerufen wird wenn auch gerade der SwingWorker > sendAndReceiveLine aufruft bekomme ich eine Exception "readtimeout" und die Verbindung zur sps bricht ab und die SPS stürtzt auch ab -.-

jetzt wollte ich Euch fragen ob ihr mir sagen könnt wie ich das lösen könnte:

kann man beim SwingWorker prioritäten vergeben?

oder ist das mit einem SwingWorker gar nicht zu realisieren?

wollte an dieser Stelle auch gleich fragen ob es gut ist einen SwingWorker mittels for-schleife recht lange laufen zu lassen, so wie ich das bei meinem code habe?

hoffe ihr versteht mein Problem und könnt mir weiterhelfen!

Klasse: DefaultClient
Java:
public class DefaultClient
{
    public DefaultClient()
    {
    }

    public static String sendAndReceiveLine(String host, int port, String text)
      throws Exception
    {
        InetAddress adress = InetAddress.getByName(host);

        Socket socket = new Socket(adress,port);
        socket.setSoTimeout(5000);

        OutputStream os = socket.getOutputStream();
        OutputStreamWriter ows = new OutputStreamWriter(os);
        BufferedWriter bw = new BufferedWriter(ows);
        bw.write(text);
        bw.newLine();
        bw.flush();

        InputStream is = socket.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String antwort = br.readLine();

        br.close();
        bw.close();
        return antwort;
    }
}

Klasse: ManuellGUI
Java:
public class ManuellGUI extends javax.swing.JFrame
{       
    private StringZerlegung sz = new StringZerlegung();
    private String[] feld = new String[20];
    public int[] anzKugeln = new int[10];
    private int[] zaehlerMagazin = new int[10];
    MesswertlisteGUI mwListe;

    public ManuellGUI()
    {
        initComponents();   
        super.setLocation(20, 100);
        mwListe = new MesswertlisteGUI();
        mwListe.setVisible(true);       
    }                      

    private void onFire1(java.awt.event.ActionEvent evt)                         
    {                             
        try
        {
            if((anzKugeln[0]) != zaehlerMagazin[0])
            {
                String text = DefaultClient.sendAndReceiveLine("192.168.0.1",
11159,"online#1#0#0#0#0#0#0#0#0#0\0");
                feld = sz.Geschw(text);
                tfVKM1.setText(feld[1]);
                zaehlerMagazin[0]++;
            }
            else
            {
                tfVKM1.setText("LEER");
            }
        }
        catch(Exception e)
        {
            JOptionPane.showMessageDialog(this, e.getMessage(),"Fehler",JOptionPane.ERROR_MESSAGE);
        }
        // Konsolenausgabe zu Testzwecken
        System.out.println("Taste Feuern 1 wurde gedrückt");
    }
}

Klasse: MesswertlisteGUI
Java:
public class MesswertlisteGUI extends javax.swing.JFrame
{
    public Kanonen kanonenModel = new Kanonen();
    StringZerlegung sz = new StringZerlegung();
    String[] htext = new String[20];
    public double speed = 0.0;
    public double speedold = 0.0;

    public MesswertlisteGUI()
    {
        initComponents();
        liListeMW.setModel(kanonenModel);
    }

    private class MySwingWorker
            extends SwingWorker<Object, Kanone>
    {
        public MySwingWorker()
                throws Exception
        {
        }

        @Override
        protected Object doInBackground()
                throws Exception
        {
            for(int i=0; i<999; i++)
            {
                System.out.println("MW Liste: der " + i + ". durchlauf");
                String text = DefaultClient.sendAndReceiveLine("192.168.0.1", 11159, "werte");
                htext = sz.Geschw(text);

                for(int a = 1; a < 11; a++)
                {
                    String status = htext[a];
                    status = status.replace('.', ',');

                    System.out.println("MW Liste: prüfung");

                    if(status.equals("ERR") || status.equals("BSY") || status.equals("OFF") || status.equals("0"))
                    {
                        System.out.println("es wurde noch kein Objekt erzeugt");
                    }
                    else
                    {
                        System.out.println("MW Liste: einlesen der " + a + ". geschwindigkeit");
                        Scanner scan = new Scanner(status);
                        System.out.println("MW Liste: Scanner");
                        speed =  scan.nextDouble();

                        if(speedold != speed)
                        {
                            speedold = speed;
                            System.out.println("MW Liste: erzeugen des " + a + ". Objekts");
                            Kanone kan = new Kanone(25, speed ,23.23);
                            publish(kan);
                        }
                    }
                }
                System.out.println("1sec warten");
                Thread.sleep(1000);
            }
            return null;
        }

        @Override
        protected void done() // wird automatisch aufgerufen
        {
//            super.done();
//            Object object = get();
            // holt Ergebnis von doInBackground
            System.out.println("MW Liste: SwingWorker fertig\n");
        }

        @Override
        protected void process(List<Kanone> chunks)
        {
            for(Kanone kan:chunks)
            {
                System.out.println("MW Liste: adden der Objekte");
                kanonenModel.add(kan);
            }
        }
    }

    private void onAktualisieren(java.awt.event.ActionEvent evt)                                 
    {                                     
        MySwingWorker worker;

        try
        {
            worker = new MySwingWorker();
            System.out.println("Mw Liste: starten des SwingWorkers");
            worker.execute();
        }
        catch (Exception e)
        {
            JOptionPane.showMessageDialog(this, "Fehler: " + e.getMessage());
        }
    }     
}
 
Vll solltest du bei der Methode "sendAndReceiveLine(..)" synchronized verwenden?

und was genau meinst du mit Prioritäten?
 
Zuletzt bearbeitet:
hab im i-net gelesen das man bei Threads mit thread.setPriority(1); die Priorität der zu bearbeitenden Threads angeben kann aber das man sich nicht darauf verlassen darf, dass der mit der höheren Priorität immer als erster behandelt wird aber er sollte schon dem mit der niedrigeren bevorzugt werden!
Galileo Computing :: Java ist auch eine Insel (8. Auflage) – 11.3 Die Zustände eines Threads

hab mir des mit synchronized angeschaut....aber weiß net so recht wie i des auf meines umsetzen soll!?
 
Zuletzt bearbeitet:
Naja also, dein Problem ist ja denke ich erstmal, dass auf diese Methode nicht von 2 Thraeds gleichzeitig darauf zugegriffen werden darf, also es sollten niemals 2 Aufrufe auf einmal ausgefürht werden. Genau das kann man mit synchrinized erreichen, es wird darauf geachtet, dass nicht 2 Threads gleichzeigtig diese Methode aufrufen.

Du schreibst einfach:

Java:
public synchronized void meineMethode() {
    //tu irgendwas
}
 
Ob das nun die Lösung ist... irgendwie habe ich das Problem noch nicht ganz verstanden, aber als kleiner Einschub: Für mich war es bisher NIE wirklich praktisch notwendig einem Thread eine andere Priorität zu geben. Irgendwo hast du wohl ein synchronisationsproblem, das nichts mit Prioritäten zu tun hat (oder haben sollte).
 
mein Problem ist das wenn zur gleichen Zeit mehr als einmal die Methode >sendAndReceiveLine aufgerufen wird die SPS abstürzt weil ich übers LAN Kabel nur entweder schicken oder empfangen kann.
wenn jetzt aber gerade ein String geschickt / empfangen wird und währenddessen von einer anderen Klasse noch eine String geschickt werden möchte gibts ein Problem.
deswegen such ich irgendeine Lösung wie ich das machen kann das sendAndReceiveLine nur einmal in verwendung ist und nicht 2mal gleichzeitig? kenn mich da aber noch nicht so aus, deswegen wäre es toll wenn ihr mir sagen könntet ob das mit synchronized möglich ist oder wie es sonst zu lösen wäre?
 
Hi Maxi, hab ne Rückfrage:

Wer oder was verändert denn die Geschwindigkeit? Kann man die Sache nicht so umdrehen, dass alle die an einem veränderten Geschwindigkeitswert interessiert sind informiert, sobald sich dieser ändert? Dann würde deine Notwendigkeit entfallen die ganze Zeit zu schauen, ob sich was getan hat...

Mfg
Bergtroll
 
@ Bergtroll

Also die Geschwindigkeit wird mittels Sensoren ausgewertet und an die SPS übergeben!
Wenns Java jetzt eine Anfrage an die SPS schickt, sprich sendAndReceiveLine aufgerufen wird schickt die SPS immer das gleiche String Protokoll zurück!
Es sieht so aus das ich mit bis zu 10 Kanonen schießen kann. Die können entweder alle gleichzeitig schießen oder jede Sekunde schießt eine Kanonen. Es sind x beliebige Szenarien! und es wird immer ein Komplettes String Feld geschickt wobei jeder Kanone 1 Feld zugewiesen ist. Und ich bekomme immer von jeder Kanone eine Rückmeldung sei es: BSY wenn die Messung noch läuft, ERR wenn ein Fehler aufgetreten ist, OFF wenn die Kanonen deaktiviert ist oder eben ein double Wert.

und nachdem pro Kanone immer etwas auszuwerten ist (BSY, ERR, OFF, Geschw) hab ich mir gedacht des alle Sekunden auszuwerten, da ja auch Exceptions zu werfen sind falls ein Error auftritt etc.

außerdem löst das nicht mein Problem oder? Denn sagen wir er erkennt gerade das ein neuer Wert vorhanden ist und möchte sich den Wert holen und ruft daher >sendAndReceiveLine auf...
und genau in dem Moment denk ich mir ich möchte jetzt mit der Kanonen 9 schießen und drücke auf den Button Feuern? Wird dann nicht erst wieder >sendAndReceiveLine 2malig aufgerufen?

Wenn ich was falsch verstanden habe dann bitte sagen!
 
Wie schon gesagt wurde: Wenn die Methode synchronized ist, kann sie nur von einem Thread gleichzeitig aufgerufen werden. Wenn das Problem dann immernoch auftritt, lag es wohl woanders.
 
hei leute!

ich hab jetzt wieder mal die SPS daheim und konnte nun testen ob das mit synchronized funktioniert.
Es geht zwar das sendAndReceiveLine nicht 2 mal gleichzeitig aufgerufen wird aber für die Programmfunktions gehts leider nicht?

ich denke ich werde es so lösen müssen wie Bergtroll vorgeschlagen hat:

Bergtroll hat gesagt.:
Hi Maxi, hab ne Rückfrage:
Wer oder was verändert denn die Geschwindigkeit? Kann man die Sache nicht so umdrehen, dass alle die an einem veränderten Geschwindigkeitswert interessiert sind informiert, sobald sich dieser ändert? Dann würde deine Notwendigkeit entfallen die ganze Zeit zu schauen, ob sich was getan hat...

könnte mir jemand einen Lösungsvorschlag geben wie ich das mache mit dem "alle informieren die daran interessiert sind???
 

Zurück
Oben