Java: UI thread does not resume in a dual-threaded application

I am currently creating a Java application using two threads:

The first stream concerns the user interface of the application, as well as the processing of the command received through the bluetooth stream.

The bluetooth stream is a bluetooth server that waits for the robot to connect and process communications.

At the moment, the user interface thread is in a waiting state () until the bluetooth thread receives a new message for processing.

The problem is that I can track the notify / notifyAll call from the bluetooth stream, but my user interface does not resume it.

Now Iโ€™m sure that I misunderstood how to properly manage synchronized threads, but I canโ€™t understand what is wrong in my software.

Here is the code for the user interface:

package mapper; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.util.ArrayList; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTable; public class MapperUI extends JFrame implements Runnable { private ArrayList<String> messageArray; public MapperUI(){ super(); build(); this.setVisible(true); new Thread(this).start(); } private void build(){ setTitle("SLAM Mapper"); setSize(600,500); setLocationRelativeTo(null); setResizable(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setContentPane(buildContentPane()); } private JPanel buildContentPane(){ JPanel main = new JPanel(); main.setLayout(new BorderLayout()); //TODO Implements auto-generated map after bluetooth communication MapPanel map = new MapPanel(); main.add(map,BorderLayout.CENTER); //TODO This fields will be buildt with stored message JTable positions = new JTable(15,2); main.add(positions,BorderLayout.EAST); JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new FlowLayout()); JButton bouton = new JButton("Start"); buttonPanel.add(bouton); JButton bouton2 = new JButton("Send"); buttonPanel.add(bouton2); main.add(buttonPanel,BorderLayout.SOUTH); return main; } public synchronized void run(){ MapperCom bt = new MapperCom(); while(true){ try { System.out.println("Mapper is Waiting......"); wait(); String message = bt.getMessage(); this.messageArray.add(message); bt.setNextCommand(processMessage(message)); notifyAll(); System.out.println("Mapper Notify"); build(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public String processMessage(String message){ String command = ""; //TODO Build a response command = "fffff\n"; return command; } } 

Here is bluetoothService:

 package mapper; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import javax.bluetooth.DiscoveryAgent; import javax.bluetooth.LocalDevice; import javax.bluetooth.UUID; import javax.microedition.io.Connector; import javax.microedition.io.StreamConnection; import javax.microedition.io.StreamConnectionNotifier; public class MapperCom extends Thread { public final UUID uuid = new UUID( "27012f0c68af4fbf8dbe6bbaf7aa432a", false); public final String name = "Server"; public final String url = "btspp://localhost:" + uuid + ";name=" + name + ";authenticate=false;encrypt=false;"; private LocalDevice local ; private StreamConnectionNotifier server ; private StreamConnection conn ; private DataInputStream din ; private DataOutputStream dout ; private String command; private String message; public MapperCom(){ try { this.command = ""; this.message = ""; System.out.println("Setting device to be discoverable..."); local = LocalDevice.getLocalDevice(); local.setDiscoverable(DiscoveryAgent.GIAC); System.out.println("Start advertising service..."); server = (StreamConnectionNotifier)Connector.open(url); System.out.println("Waiting for incoming connection...\n"); conn = server.acceptAndOpen(); System.out.println("Client Connected..."); din = new DataInputStream(conn.openInputStream()); dout = new DataOutputStream(conn.openOutputStream()); new Thread(this).start(); } catch (Exception e) { System.out.println("Exception Occured: " + e.toString()); } } @Override public synchronized void run(){ System.out.println("Bluetooth Thread Started"); while(true){ try { String cmd = ""; char c; System.out.println("Waiting for message"); while (((c = din.readChar()) > 0) && (c!='\n') ){ System.out.println("Char received :"+c); cmd = cmd + c; } storeMessage(cmd); System.out.println("Bt Notify......"); notifyAll(); System.out.println("Bt is Waiting for a command from mapper......"); wait(); sendResponse(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void sendResponse(){ try { dout.writeChars(command); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public synchronized String getMessage(){ return this.message; } public synchronized void storeMessage (String data){ this.message = data; System.out.println("Received " + data); } public synchronized int setNextCommand (String data){ int result = -1; //TODO Implement proper protocol this.command = data; System.out.println("Sending " + data); return result; } } 
+4
source share
3 answers

The following is one sample program. Basically, there is a need for a common lock between two threads if you want to communicate using wait and notify.

 package ravi.tutorial.java.threads; public class TestThreads { /** * @param args */ public static void main(String[] args) { CommonLock commonLock = new CommonLock(); Thread1 thread1 = new Thread1(commonLock); Thread2 thread2 = new Thread2(commonLock); thread1.start(); thread2.start(); } } /* * Common monitor lock between both threads, used for communication using wait * notify. */ class CommonLock { } // Extending Thread instead of Runnable as its just a test class Thread1 extends Thread { private CommonLock commonLock; public Thread1(CommonLock commonLock) { this.commonLock = commonLock; } public void run() { System.out.println("Started thread 1"); System.out.println("waiting thread 1"); try { // TO wait on commonLock, first need to get lock on commonLock. SO // put synchronized block of commonLock. synchronized (commonLock) { commonLock.wait(); } } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("DONE waiting thread 1 as I got notification from THread 2"); } } class Thread2 extends Thread { private CommonLock commonLock; public Thread2(CommonLock commonLock) { this.commonLock = commonLock; } public void run() { System.out.println("Running thread 2"); try { System.out.println("Sleeping thread 2"); // Just take gap of 2 sec before notifying. Thread.sleep(2000); // TO notify on commonLock, first need to get lock on commonLock. SO // put synchronized block of commonLock. synchronized (commonLock) { System.out.println("Notifying thread 2"); commonLock.notifyAll(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 
+1
source

I think when you call notifyAll() , it calls this.notifyAll() . Which are no other elements awaiting in the same class. So what can you do, you use the same object for both classes and call obj.wait() and obj.notifyAll() . This will work.

+5
source

Look at it: Theme Tutorial

  • wait () tells the calling thread to abandon the monitor and go to sleep until some other thread enters the same monitor, and calls
    inform().

  • notify () wakes up the first thread that calls wait () on the same object.

  • notifyAll () wakes up all the threads that called wait () on the same object. The thread with the highest priority will be executed first.

This is a basic misunderstanding of the concept of threads in Java.

0
source

Source: https://habr.com/ru/post/1446410/


All Articles