我正在用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
非常感谢您的帮助,并感谢您的宝贵时间!
答案 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;
}
您可能会使用一些运算符来使其执行所需的操作,也可以使用不同的调度程序从不同的线程策略中进行选择。
您还可以在您发布的主题中转换您的输入,可以直接从您的输入中创建一个可观察的主题或主题。