我正在构建一个交互式 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/