Interthread-Kommunikation

delphinis

Mitglied
Hallo,
versuche verzweifelt eine Interthread-Kommunikation hinzukriegen. Dazu hab ich mein Programm auf das nötigste Reduziert.
- Hauptprogramm mit zwei Threads
- Der eine Thread schickt dem zweiten alle 5 Sekunden ein Notify
- Der zweite meldet dies dem User
- alles ist über ein Object obj synchronisiert
Das nachfolgende Programm ist lauffähig.

Problem:
Beide Threads arbeiten, aber der zweite Thread reagiert nicht mit wait() auf das notify des anderen.

Java:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;

public class ThreadTest extends JPanel implements ActionListener {
  private static final long     serialVersionUID = 1L;
  JPanel 												topPanel;
  JButton                       testButton;
  String                        programname      = "ThreadTest";
  static JFrame                 frame;
  JTextArea                     logTextArea;
  JScrollPane 									logTextAreaScrollPane;

  Object obj = new LogData();
  Thread timeThread;
  Thread receiveThread;
  
  public static void main(String[] args) {
    frame = new JFrame(); // Frame = Window
    frame.setBounds(1920, 0, 600, 1200);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new ThreadTest());
    frame.setVisible(true);
  }

  public ThreadTest() {
  	try {
  		frame.setTitle(programname);
      // **************************************************************************************************
      // GUI BEGIN
      // **************************************************************************************************
      try {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
      } catch (Exception e) {}
      topPanel = new JPanel();
      frame.add(topPanel);
      this.add(topPanel, BorderLayout.NORTH);
      
      topPanel.paintAll(this.getGraphics());

      testButton = new JButton("Send");
      testButton.setBounds(20, 20, 95, 22);
      topPanel.add(testButton);
      testButton.addActionListener(this);
            
      receiveThread = new Thread(new ReceiceThread());
      receiveThread.start();
    	try {
    		Thread.sleep(300);
    	} catch (InterruptedException e) {
    		JOptionPane.showMessageDialog(frame.getRootPane(), e.getMessage());
    	}
      timeThread = new Thread(new TimeThread());
      timeThread.start();
    } catch (RuntimeException runtimeExeption) {
      runtimeExeption.printStackTrace();
      JOptionPane.showMessageDialog(this.getRootPane(), "Runtime exception:" + runtimeExeption.getMessage());
    }
  }
  
  public void actionPerformed(ActionEvent event) {
    String cmd = event.getActionCommand();
    if (cmd.equals("Send")) {
    }
  }
  
  class TimeThread implements Runnable {
    @Override public void run() {
      while (true) {
      	synchronized(obj) {
	      	try {
	      		Thread.sleep(5000);
	      		obj.notify();
	      	} catch (InterruptedException e) {
	      		JOptionPane.showMessageDialog(frame.getRootPane(), e.getMessage());
	      	}
      	}
      }
    }
  }
  
  class ReceiceThread implements Runnable {    
    @Override public void run() {
      while (true) {
      	synchronized(obj) {
	      	try {
	      		obj.wait();
		      	java.awt.Toolkit.getDefaultToolkit().beep();

	      		JOptionPane.showMessageDialog(frame.getRootPane(), "Meldung erhalten");
	      	} catch (InterruptedException e) {
	      		JOptionPane.showMessageDialog(frame.getRootPane(), e.getMessage());
	      	}
	      }
    	}
    }
  }  
  
}

Vielen Dank zum Voraus

PS: Kann man mit Notify auch einen Wert oder ein Objekt mitsenden?
 
Hallo Barista,
Vielen Dank.
Ja, stimmt, der Thread wird (zeitweise) geweckt. Dies ist mir nicht aufgefallen, da es offenbar eine (sehr) unbestimmte Zeit dauert, bis der Thread auf das notify reagiert. (notify wird wie erwartet alle 5 Sekunden ausgeführt, aber der andere Thread erwacht nur sporadisch)
Zum testen hab ich nach dem notif() noch ein Beep reingetan um zu sehen, wann er dort durchfährt.
Bei mir jedenfalls kommt das Fenster nicht bei jedem notify und fünf Sekunden sollten selbst für Windows reichen ;-)?
Wie funktioniert das bei dir???

PS: Sorry an alle, die das Programmfenster vergebens gesucht haben. Zeile 27 müsste man folgendermassen ändern:
Java:
frame.setBounds(0, 0, 600, 600);
 
Wie funktioniert das bei dir???

Du hast etwas zu hohe Erwartungen an mich,
ich habe Dein Prog nicht bei mir lokal eingerichtet.

Ich beantworte nur die Frage, mache aber nicht Deinen Kram fertig.

Du kannst auch mal notifyAll versuchen.
 
Zuletzt bearbeitet:
Sorry, ich wollte dich nicht nötigen.
Bei diesem Problem steh ich halt auf dem Schlauch, weil es theoretisch funktionieren sollte (was du mir ja auch bestätigt hast), es praktisch aber halt nicht wirklich zu funktionieren scheint...

NotifyAll hat leider auch nichts gebracht. Denke, dies ist bei einem zu benachrichtigenden Thread funktionell ja wohl auch nichts anderes.
 
Zuletzt bearbeitet:
OK, hätt mich zwar schon interessiert wieso's mit notify nicht lief aber ich hab's jetzt mit einer SynchronousQueue hingebracht. Nachdem ich auch beide Threads zuerst kreiert hab und dann erst gestartet, läuft es wie gewollt.
Für dijenigen die's interessiert, nachstehend noch den Code.

Danke für deine Hilfe, Barista

Java:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.SynchronousQueue;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;

public class ThreadQueueTest extends JPanel implements ActionListener {
  private static final long     serialVersionUID = 1L;
  JPanel 												topPanel;
  JButton                       testButton;
  String                        programname      = "ThreadTest";
  static JFrame                 frame;
  JTextArea                     logTextArea;
  JScrollPane 									logTextAreaScrollPane;

  Object obj = new Object();
  Thread timeThread;
  Thread receiveThread;
  SynchronousQueue<Integer> queue = new SynchronousQueue<Integer>();
  
  public static void main(String[] args) {
    frame = new JFrame(); // Frame = Window
    frame.setBounds(0, 0, 600, 600);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new ThreadQueueTest());
    frame.setVisible(true);
  }

  public ThreadQueueTest() {
  	try {
  		frame.setTitle(programname);
      // **************************************************************************************************
      // GUI BEGIN
      // **************************************************************************************************
      try {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
      } catch (Exception e) {}
      topPanel = new JPanel();
      frame.add(topPanel);
      this.add(topPanel, BorderLayout.NORTH);
      System.out.println(queue.size());

      
      topPanel.paintAll(this.getGraphics());

      testButton = new JButton("Send");
      testButton.setBounds(20, 20, 95, 22);
      topPanel.add(testButton);
      testButton.addActionListener(this);
            
/*    	try {
    		Thread.sleep(300);
    	} catch (InterruptedException e) {
    		JOptionPane.showMessageDialog(frame.getRootPane(), e.getMessage());
    	}*/
      timeThread = new Thread(new TimeThread());
      
      receiveThread = new Thread(new ReceiceThread());
      timeThread.start();
      receiveThread.start();
    } catch (RuntimeException runtimeExeption) {
      runtimeExeption.printStackTrace();
      JOptionPane.showMessageDialog(this.getRootPane(), "Runtime exception:" + runtimeExeption.getMessage());
    }
  }
  
  public void actionPerformed(ActionEvent event) {
    String cmd = event.getActionCommand();
    if (cmd.equals("Send")) {
    }
  }
  
  class TimeThread implements Runnable {
  	Integer i = 0;
    @Override public void run() {
      while (true) {
	      	try {
      	synchronized(receiveThread) {
	      		System.out.println("sleep\n");
	      		Thread.sleep(5000);
	      		System.out.println("awaken");
	      		queue.put(i);
//	      		receiveThread.notify();
//	      		java.awt.Toolkit.getDefaultToolkit().beep();
      	}
	      	} catch (InterruptedException e) {
	      		JOptionPane.showMessageDialog(frame.getRootPane(), e.getMessage());
	      	}
      	i++;
      }
    }
  }
  
  class ReceiceThread implements Runnable {
    @Override public void run() {
    	Integer i;
      while (true) {
	      	try {
      	synchronized(this) {
	      		i = (Integer)queue.take();
//	      		this.wait();
		      	java.awt.Toolkit.getDefaultToolkit().beep();

	      		JOptionPane.showMessageDialog(frame.getRootPane(), "Queue element Nr. " + i.toString());
    	}
	      	} catch (InterruptedException e) {
	      		JOptionPane.showMessageDialog(frame.getRootPane(), e.getMessage());
	      	}
	      }
    }
  }  
  
}
 

Neue Themen


Zurück
Oben