Threads Objekt im Konstruktor anders wie im Run()-Block

Dieses Thema Threads - Objekt im Konstruktor anders wie im Run()-Block im Forum "Allgemeine Java-Themen" wurde erstellt von patrick_e, 5. Dez. 2016.

Thema: Objekt im Konstruktor anders wie im Run()-Block Hallo, ich habe ein Programm das Daten aus einem Socket ausliest und danach analysiert. Klasse 1: Liest die...

  1. Hallo,
    ich habe ein Programm das Daten aus einem Socket ausliest und danach analysiert.

    Klasse 1: Liest die Nachricht aus einer Socketverbindung aus. Diese Klasse ist ein Thread und beeinhaltet eine Endlosschleife in der die Daten ausgelesen werden.
    Klasse 2: Analysiert die ausgelesene Nachricht. Diese Klasse ist auch ein Thread und für jede Nachricht wird ein extra Thread angelegt.

    Ich habe folgendes Problem. Im Konstruktor der Klasse 1 gibt es das Objekt transpMsg. Diese Objekt wird hier noch korrekt gefüllt. Sobald aber der Thread gestartet wird, beinhaltet transpMsg andere Daten. Wenn ich in der Funktion startAnalyze() ein sleep(50) einfüge, funktioniert es einwandfrei.

    Ich hoffe ich habe es einigermaßen verständlich formuliert.
    Vielen Dank schon mal für eure Mühe.

    Klasse 1
    Code (Java):
    public class AntMessage extends Thread {

        private static final Logger LOG = Logger.getLogger(AntMessage.class);


        public AntMessage(Antenne ant, Service_Manager sm, Guardserver guard) {
            this.sm = sm;
            this.ant = ant;
            this.guard = guard;
            executor = Executors.newCachedThreadPool();
        }

        public void run() {
            /*
             Dieser ArrayList beinhaltet die Hexa Daten die von der Antenne gesendet werden
             */

            Vector<String> hexMsg = new Vector<String>();

            connect();

            initializeSocket();
            /*
             Start der Endlos Schleife
             Hier werden die Nachrichten der Antenne abgerufen
             */

            while (!isInterrupted()) {
                try {
                    int msg = readData();
                    /*
                     Übersetzung der Byte Nachricht in einen Hex String
                     */

                    String hexdata = normalizeHexdata(msg);
                    String hexdata2 = "";
                    /*
                     Wenn die Nachricht vollständig ist beginnt sie immer mit "1f"
                     */

                    if (msg == VAR_CMD_START) {
                        int msg2 = 0;
                        try {
                            msg2 = antInput.read();
                            hexdata2 = normalizeHexdata(msg2);
                        } catch (Exception ex) {
                            LOG.error(ex.getMessage());
                            ex.printStackTrace();
                        }
                        if (msg2 != VAR_CMD_START) {
                            //Wenn das zutrifft dann Startet hier immer die Nachricht
                            if (hexMsg.size() > 11) {

                                startAnalyze(new TranspMsg(hexMsg));

                                lastPing = new Date().getTime();
                            }
                            hexMsg.clear();
                            hexMsg.add(hexdata);
                            hexMsg.add(hexdata2);
                        } else {
                            //Zweimal 1F hintereinander
                            hexMsg.add(hexdata);
                        }
                    } else {
                        hexMsg.add(hexdata);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    public void startAnalyze(TranspMsg msg) {
            //Analyse der Nachricht starten

            final MessageAnalyse msa = new MessageAnalyse(msg, this);
            //executor.execute(msa);
            new Thread(msa).start();
            try {
             sleep(50);
             } catch (InterruptedException ex) {
             java.util.logging.Logger.getLogger(AntMessage.class.getName()).log(Level.SEVERE, null, ex);
             }

        }

        }
    Klasse 2
    Code (Java):
    public class MessageAnalyse implements Runnable {


        public MessageAnalyse(TranspMsg transpMsg, AntMessage antMsg) {
            synchronized (getClass()) {
                this.transpMsg = transpMsg;
                this.antMsg = antMsg;

                this.ant = antMsg.ant;
                this.guard = antMsg.guard;
                this.sql = guard.sql;
                this.dbCache=guard.dbCache;
            }
            if (transpMsg.isIsKeyboardinput()) {
                System.out.println("KEYBOARD2 " + transpMsg.toString() + " " + this.transpMsg.toString());
            }

        }

        @Override
        public synchronized void run() {
            /*
             Ist die Nachricht eine "Message over the Air" dann springt das Programm in folgende Schleife.
             */


            if (transpMsg.isIsKeyboardinput()) {
                System.out.println("KEYBOARD3 " + this.transpMsg.toString() + this.toString());
            }
     
    Zuletzt von einem Moderator bearbeitet: 5. Dez. 2016
  2. Vielleicht hilft dir das Java-Tutorial weiter. Hier klicken --> (Klick)
  3. Am besten wartest du mal, bis der Thread zuende gelaufen ist und rufst dann nochmal die Daten ab.
    Während der Thread läuft, können falsche Standbilder entstehen.

    Willst du wirklich getClass() synchronisieren? Dabei sperrst du die Klasse, nicht aber die Objekte davon. Vielleicht ist ja synchronized(this) das, was du willst.
     
  4. Vielen Dank für deine Antwort.
    Ich kann nicht warten bis er zuende gelaufen ist, da ich dann Geschwindigkeitsprobleme bekomme. Daher nehme ich ja einen Thread und keine normale Klasse. Das synchronized (this) hat leider nicht den gewünschten Erfolg gebracht.
     
  5. Ich meine den Übeltäter gefunden zu haben. in meiner Klasse TranspMsg verändert sich immer wieder die Collection hexMsg. Alle anderen Variablen bringen mir immer konstante Werte. Wie bekomme ich hexMsg Threadsafe? Ich arbeite schon mit Collections.synchronizedList(new ArrayList<String>()); aber das bringt leider nichts. Anbei die Klasse.
    Code (Java):
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;

    /**
    *
    * @author pe
    */

    public class TranspMsg {

        private  List<String> hexMsg=Collections.synchronizedList(new ArrayList<String>());
        private final String transpId;
        private final int meldungsart;
        private final int laenge;
        private final String bewegung;
        private final String msgType;
        private final boolean isMessageOTA;
        private final int quality;
        private final boolean extendedMsg;
        private final double temp;
        private final double voltage;
        private final boolean isKeyboardinput;
        private String outString;

        public TranspMsg(final List<String> hexMsg) throws Exception {
            synchronized (this) {
                this.hexMsg = hexMsg;
            }

            transpId = hexMsg.get(8) + hexMsg.get(7) + hexMsg.get(6) + hexMsg.get(5);
            meldungsart = Integer.parseInt(hexMsg.get(4).substring(1), 16);
            laenge = Integer.parseInt(hexMsg.get(2), 16);
            bewegung = hexMsg.get(9).substring(0, 1);
            msgType = hexMsg.get(4).substring(1);
            isMessageOTA = hexMsg.get(1).equals("99");
            quality = Integer.parseInt((String) hexMsg.get(hexMsg.size() - 2), 16);
            if (laenge > 7 && hexMsg.size() > 12) {
                extendedMsg = true;
            } else {
                extendedMsg = false;
            }
            if (extendedMsg) {
                String volt = hexMsg.get(10);
                int volti = Integer.parseInt(volt, 16);
                voltage = (new Double(volti) + 100) / 100;

                int tempT = (Integer.parseInt(hexMsg.get(11) + hexMsg.get(12), 16));
                temp = ((Double.parseDouble((tempT - 500) + "")) / 10);
            } else {
                temp = 0.0;
                voltage = 0.0;
            }
            if (hexMsg.size() > 12 && hexMsg.get(10).equals("08")) {
                isKeyboardinput = true;
            } else {
                isKeyboardinput = false;
            }
            outString = "";
            for (int i = 0; i < hexMsg.size(); i++) {
                outString += (hexMsg.get(i) + " ");
            }
        }

        public synchronized List<String> getHexMsg() {
            return hexMsg;
        }
     
  6. Entweder du verwendet Semaphoren, erweiterst deinen synchronized Block oder verwendet wait/notify.
    Schau dir mal die entsprechenden Konstrukte an.

    Oder verwende den Getter statt direkt das Attribut. Dann hast du aber einen kleinen Design-Fehler.
     
  7. Ich habe den synchronized Block erweitert aber nichts hat sich geändert. Ich verwende immer den Getter(getHexMsg()) aber die List ist immer noch eine andere wie zum Beispiel die Ausgabe outString. Ich verzweifel so langsam an dem Problem.
     
  8. Das System.out.println ist ja nicht im synchronized Block.
    Vorsicht bei Paralletität und System.outs.
     
  9. Die Liste, die du hier erzeugst
    Code (Java):
        private  List<String> hexMsg=Collections.synchronizedList(new ArrayList<String>());
     
    wird nie benutzt, da sie im Konstruktor mit der vom Aufrufer übergebenen Liste überschrieben wird:
    Code (Java):

        public TranspMsg(final List<String> hexMsg) throws Exception {
             synchronized (this) {
                 this.hexMsg = hexMsg;
             }
     
    Wenn der Aufrufer des Konstruktors später die Liste ändert, ist sie auch in deiner Klasse geändert.
     
  10. Die Liste wird nicht geändert. Sie wird nur einmal hinzugefügt....
    Jedoch ändert sie sich immer wieder in der erstellten Klasse TranspMsg. Obwohl sich keinerlei Setter in der Klasse befinden.
    Code (Java):
    public class AntMessage extends Thread {

        private static final Logger LOG = Logger.getLogger(AntMessage.class);
        Service_Manager sm = null;
        Socket s = null;
        Antenne ant = null;
        BufferedInputStream antInput = null;
        DataOutputStream anOutput = null;
        static int VAR_CMD_START = 31;
        long startmillis;
        int count = 0;
        Guardserver guard = null;
        static final String SYSTEM_NAME = "SYSTEM";
        String antwortHost = "";
        Boolean fehler = false;
        Long lastPing = new Date().getTime();

        public AntMessage(Antenne ant, Service_Manager sm, Guardserver guard) {
            this.sm = sm;
            this.ant = ant;
            this.guard = guard;
        }

        public void run() {
            /*
             Dieser ArrayList beinhaltet die Hexa Daten die von der Antenne gesendet werden
             */


            List<String> hexMsg = Collections.synchronizedList(new ArrayList<String>());
         
            //Vector<String> hexMsg = new Vector<String>();

            connect();

            initializeSocket();
            /*
             Start der Endlos Schleife
             Hier werden die Nachrichten der Antenne abgerufen
             */

            while (!isInterrupted()) {
                try {
                    int msg = readData();
                    /*
                     Übersetzung der Byte Nachricht in einen Hex String
                     */

                    String hexdata = normalizeHexdata(msg);
                    String hexdata2 = "";
                    /*
                     Wenn die Nachricht vollständig ist beginnt sie immer mit "1f"
                     */

                    if (msg == VAR_CMD_START) {
                        int msg2 = 0;
                        try {
                            msg2 = antInput.read();
                            hexdata2 = normalizeHexdata(msg2);
                        } catch (Exception ex) {
                            LOG.error(ex.getMessage());
                            ex.printStackTrace();
                        }
                        if (msg2 != VAR_CMD_START) {
                            //Wenn das zutrifft dann Startet hier immer die Nachricht
                            if (hexMsg.size() > 11) {
                               
                                synchronized (this) {
                                    List<String> hexMsg2 = hexMsg;
                                    TranspMsg tmsg=new TranspMsg(hexMsg2);
                                    startAnalize(tmsg);
                                }

                                lastPing = new Date().getTime();
                            }
                            hexMsg.clear();
                            hexMsg.add(hexdata);
                            hexMsg.add(hexdata2);
                        } else {
                            //Zweimal 1F hintereinander
                            hexMsg.add(hexdata);
                        }
                    } else {
                        hexMsg.add(hexdata);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }
     
  11. Hier gibt es zwei Variablen, die das gleiche Objekt referenzieren:
    Code (Java):
    List<String> hexMsg2 = hexMsg;
    TranspMsg tmsg=new TranspMsg(hexMsg2);
     
    eine Änderung von hexMsg ändert auch hexMsg2, und das geschieht hier:
    Code (Java):
    hexMsg.clear();
    hexMsg.add(hexdata);
     
     
  12. Ah jetzt hab ich es verstanden....
    Also müsste ich es so machen...
    Code (Java):
    synchronized (this) {
                                    List<String> hexMsg2 = Collections.synchronizedList(new ArrayList<String>());
                                    for(int i=0;i<hexMsg.size();i++){
                                        hexMsg2.add(hexMsg.get(i));
                                    }
                                    TranspMsg tmsg=new TranspMsg(hexMsg2);
                                    startAnalize(tmsg);
                                }
    Oder geht das noch performanter?
     
  13. Schau dir jetzt hier den Kurs an und lernen Java zu programmieren: --> Hier klicken, um mehr zu erfahren (Klick)