有数据时将数据发送到串行端口

时间:2019-05-13 19:55:29

标签: java multithreading wait synchronized

我正在用14x14矩阵构建一个交互式LED桌子,其中包括可寻址的LED灯条,用于大学作业。这些是由2个arduinos控制的,它们从运行服务器的Pi上获取有关哪个LED应该具有哪个RGB值的数据,该服务器运行应该在LED桌子上玩的几个游戏。为了控制游戏,我将相应的int代码从android应用发送到运行在Raspi上的服务器。

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

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

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

所以我一直在尝试运行while(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(),它没有改变结果。

在其中一个游戏(井字游戏)中,每次游戏更新并把矩阵发送到arduinos后,我都调用此方法:

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

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

1 个答案:

答案 0 :(得分:0)

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

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

您可以编写类似的内容(不要从字面上理解)。

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

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

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

相关问题