Java:UI线程在双线程应用程序中未恢复

Java:UI线程在双线程应用程序中未恢复,java,multithreading,bluetooth,Java,Multithreading,Bluetooth,我目前正在使用两个线程构建Java应用程序: 第一个线程是关于应用程序的UI,以及通过蓝牙线程接收的命令的处理 蓝牙线程是等待机器人连接并处理通信的蓝牙服务器 到目前为止,UI线程处于wait()状态,直到bluetooth线程获得要处理的新消息 问题是,我可以从蓝牙线程跟踪notify/notifyAll调用,但我的UI没有恢复其活动 我现在确信我误解了管理同步线程的正确方法,但我无法找出我的软件中的错误 以下是UI的代码: package mapper; import java.awt.B

我目前正在使用两个线程构建Java应用程序:

第一个线程是关于应用程序的UI,以及通过蓝牙线程接收的命令的处理

蓝牙线程是等待机器人连接并处理通信的蓝牙服务器

到目前为止,UI线程处于wait()状态,直到bluetooth线程获得要处理的新消息

问题是,我可以从蓝牙线程跟踪notify/notifyAll调用,但我的UI没有恢复其活动

我现在确信我误解了管理同步线程的正确方法,但我无法找出我的软件中的错误

以下是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;
}
}

我想当你调用
notifyAll()
时,它会调用
this.notifyAll()
。没有其他元素在同一个类中等待。因此,您可以在两个类上共享同一个对象,并调用
obj.wait()
obj.notifyAll()
。它会起作用的

看看这个:

  • wait()告诉调用线程放弃监视器并转到
    睡眠,直到其他线程进入同一监视器并调用
    通知()

  • notify()唤醒在上调用wait()的第一个线程 同一个物体

  • notifyAll()唤醒在上调用wait()的所有线程 同样的目标。优先级最高的线程将首先运行


这是Java中对线程概念的主要误解。

下面是一个示例程序。如果您希望使用wait¬ify进行通信,那么两个线程之间基本上需要一些公共锁

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();
        }

    }

}

绝对不要让UI线程进入等待状态。这会冻结您的GUI。非常感谢您的完整实现
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();
        }

    }

}