我目前正在使用两个线程构建Java应用程序:
第一个线程是关于应用程序的UI,以及通过蓝牙线程接收的命令处理。
蓝牙线程是等待机器人连接和处理通信的蓝牙服务器。
截至目前,UI线程处于wait()状态,直到蓝牙线程获得要处理的新消息。
问题是,我可以跟踪来自蓝牙线程的notify / notifyAll调用,但是我的UI没有恢复它的活动。
我现在肯定我误解了管理同步线程的正确方法,但我无法弄清楚我的软件出了什么问题。
以下是用户界面的代码:
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;
}
}
这是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;
}
}
答案 0 :(得分:5)
我想当您致电notifyAll()
时,会拨打this.notifyAll()
。其中没有其他元素在同一个班级中等待。因此,您可以做的是在两个类上共享相同的对象并调用obj.wait()
和obj.notifyAll()
。它会工作。
答案 1 :(得分:1)
以下是一个示例程序。基本上,如果你想使用wait&amp; amp;通知。
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();
}
}
}
答案 2 :(得分:0)
看看这个:Thread tutorial
wait()告诉调用线程放弃监视器并转到
睡觉直到其他一些线程进入同一个监视器并调用
notify()。notify()唤醒调用wait()的第一个线程 同一个对象。
notifyAll()唤醒所有调用wait()的线程 同一个对象。优先级最高的线程将首先运行。
这是对Java中线程概念的主要误解。