java - 当数据可用时发送数据到串口

标签 java multithreading wait synchronized

我正在构建一个交互式 LED table ,该 table 具有 14x14 矩阵,由可寻址 LED 灯条组成,用于大学作业。这些由 2 个 arduino 控制,它们从运行服务器的 Pi 获取有关哪个 LED 应该具有哪个 RGB 值的数据,该服务器运行多个应该可以在 LED table 上玩的游戏。为了控制游戏,我将相应的 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(),它没有改变结果。

在其中一款游戏(Tic Tac Toe)中,我在每次游戏结束后调用此方法来更新矩阵并将其发送到arduinos:

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

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

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

编辑:

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

非常感谢您的帮助,并提前感谢您抽出时间!

最佳答案

您正在处理可能在不同线程上运行的异步更新,我认为最好的匹配是使用 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;
    }

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

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

关于java - 当数据可用时发送数据到串口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56119084/

相关文章:

java - JDBC 连接关闭

java - 从外部 JVM 通过 Remote bean 调用 EJB3 Local bean

c - 使用多线程对C中的非套接字错误进行套接字操作

java - 我的java代码不同步

java - Java XML解析

java - 无法从 Java 将 boolean 首选项存储到 Windows 10 注册表,而整数和字符串可以正确存储

ios - 在后台线程中加载 UIImage

c++ - 在线程争用情况下等待的最快方法

c++ - 等到函数完成后再继续 main(一个线程)

java - 等待线程是否重新访问同步方法中的代码