【问题标题】:Send data to serial port when data is available数据可用时发送数据到串口
【发布时间】:2019-09-30 19:28:56
【问题描述】:

我正在构建一个 14x14 矩阵的交互式 LED 表,该矩阵由可寻址的 LED 灯条组成,用于大学作业。这些由 2 个 arduino 控制,这些 arduino 从运行服务器的 Pi 中获取关于哪个 LED 应该具有哪个 RGB 值的数据,该服务器运行多个游戏,这些游戏应该可以在 LED 表上播放。为了控制游戏,我将相应的 int 代码从 android 应用程序发送到运行在 Raspi 上的服务器。

串口通信是通过jSerialComm实现的。我面临的问题是,我不想通过串行端口永久发送数据,但只是在此刻,当指定矩阵的新数组可用时。

因此,我不想忙于等待并永久检查矩阵是否已更新,我不想检查更新

    while(!matrixUpdated) {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {}
    }

所以我一直在尝试运行一段时间(true),在其中我调用 wait(),所以线程停止,直到我通过调用 notify 唤醒线程,当更新的矩阵可用时。

我在串行线程中的 run() 方法此刻看起来是这样的:

@Override
public void run() {
    arduino1.setComPortTimeouts(SerialPort.TIMEOUT_SCANNER, 0, 0);
    arduino2.setComPortTimeouts(SerialPort.TIMEOUT_SCANNER, 0, 0);

    try {
        Thread.sleep(100);
    } catch (Exception e) {}

    PrintWriter outToArduino1 = new PrintWriter(arduino1.getOutputStream());
    PrintWriter outToArduino2 = new PrintWriter(arduino2.getOutputStream());

    while(true) {

        try {
            wait();
        } catch (InterruptedException e) {}

        System.out.println("Matrix received");

        outToArduino1.print(matrix);
        outToArduino2.print(matrix);
    }
}

我通过嵌套在同一个类中的这个方法唤醒线程:

public void setMatrix(int[][][] pixelIdentifier) {
    matrix = pixelIdentifier;
    notify();
}

我也尝试了 notifyAll() ,它没有改变结果。

在其中一个游戏(井字游戏)中,我在每次游戏回合后调用此方法来更新矩阵并将其发送到 arduino:

private void promptToMatrix() {
    synchronized (GameCenter.serialConnection) {
        GameCenter.serialConnection.setMatrix(matrix);
    }
}

我之前在没有使用同步块的情况下调用它,但是当我在 StackOverflow 上阅读了许多关于该主题的文章时,我已经读到应该为此使用同步。此外,我还读到不建议使用 wait() 和 notify(),但是由于分配需要很快完成,我不知道是否有任何其他方法有意义,因为我不想重组整个应用程序因为我在玩游戏时最多运行 5 个线程(由于用于通信的线程等)。

如果有可能使用 wait() 和 notify() 来解决这个问题,我将非常感激听到如何做到这一点,因为我无法真正理解同步块如何正常工作完成等等。 但是,如果这样的解决方案是不可能的,或者也会以重组整个应用程序而告终,我也愿意接受不同的建议。指出不推荐使用 wait() 和 notify() 但这对我没有帮助,因为我已经经常阅读,我知道这一点,但如果可能的话,更喜欢在这种情况下使用它!!!

编辑:

The application executes like this: 
Main Thread
|--> SerialCommunication Thread --> waiting for updated data
|--> NetworkController Thread
     |--> Client Thread --> interacting with the game thread
          |--> Game Thread --> sending updated data to the waiting SerialCommunication Thread

非常感谢您的帮助,并提前感谢您的宝贵时间!

【问题讨论】:

    标签: java multithreading wait synchronized


    【解决方案1】:

    您正在处理可能在不同线程上运行的异步更新,我认为最好的匹配是使用RxJava

    您可以使用Subject 接收矩阵事件,然后订阅它以更新 LED。

    你可以这样写(不要太字面意思)。

        public static void main(String[] args) {
            int[][] initialValue = new int[32][32];
    
            BehaviorSubject<int[][]> matrixSubject = BehaviorSubject.createDefault(initialValue);
    
            SerialPort arduino1 = initSerial("COM1");
            SerialPort arduino2 = initSerial("COM2");;
    
            PrintWriter outToArduino1 = new PrintWriter(arduino1.getOutputStream());
            PrintWriter outToArduino2 = new PrintWriter(arduino2.getOutputStream());
    
            Observable<String> serializedMatrix = matrixSubject.map(Sample::toChars);
    
            serializedMatrix.observeOn(Schedulers.io()).subscribe(mat -> {
                // Will run on a newly created thread  
                outToArduino1.println(mat);
            });
    
            serializedMatrix.observeOn(Schedulers.io()).subscribe(mat -> {
                // Will run on a newly created thread 
                outToArduino2.println(mat);
            });
    
            // Wait forever
            while(true) {
                try {
                    // get your matrix somehow ...
                    // then publish it on your subject
                    // your subscribers will receive the data and use it.
                    matrixSubject.onNext(matrix);
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // SWALLOW error
                }
            }
    
        }
    
        public static String toChars(int[][] data) {
            // Serialize data
            return null;
        }
    
    

    您可以使用多种运算符来使其执行所需的操作,也可以使用不同的调度程序从不同的线程策略中进行选择。

    您还可以在您发布的主题中转换您的输入,可以直接从您的输入创建可观察对象或主题。

    【讨论】:

    • 不知道是不是异步等待。具体来说,我的应用程序执行如下:主线程启动一个用于串行通信的线程和一个等待客户端连接的新 NetworkController 线程。一旦客户端连接,就会启动一个新的 ClientThread,它等待客户端的用户输入,并根据输入启动或结束游戏线程或访问游戏控件。游戏每回合都会更新通过串行线程发送的数据。
    • 我仍然想看看 RXJava,它可以巧妙地解决许多这些问题。它确实抽象了大部分问题,尤其是等待。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多