英文:
Method keeps running and sending the same information even for different request grpc
问题
我正在尝试实现GRPC,但在这样做时,我从服务器获得了正确的响应。如果我停止服务器,然后再次运行它并使用我实现的其他请求,它能正常工作。然而,如果我尝试在第一个请求中的一次请求之后立即进行第二次请求,我会得到相同的响应。就像是在循环一样。
以下是我从客户端使用的这两个方法:
public void setSpaces(int id) {
// ... 代码略 ...
}
public void setFull(int id) {
// ... 代码略 ...
}
这两个方法旨在向服务器发送请求,以更改“停车场”的状态。如果我使用setFull
方法发送请求,我会得到一个响应,说停车场已满等。
以下是服务器上的这些方法:
public void setSpaces(CarParkToUpdateRequest request, StreamObserver<carParkResponse> rStreamObserver) {
// ... 代码略 ...
}
public void setFull(CarParkToUpdateRequest request, StreamObserver<carParkResponse> rStreamObserver) {
// ... 代码略 ...
}
我认为问题很可能与服务器方法有关,但似乎无法弄清楚。这是我存储数据的地方:
package CarParkOperations.proto.cp;
import java.util.ArrayList;
public class Car extends ArrayList<CarPark> {
// ... 代码略 ...
}
如果有建议,将不胜感激。
英文:
I am trying to implement GRPC and when i do so I get the correct response from the server and if I stop the server and run it again and use the other request that I implemented it works however if I try and make a second request straight after making one in from the first request I get the same response. It's like it is looping.
These are the two methods I am using from the client:
public void setSpaces(int id) {
channel =ManagedChannelBuilder.forAddress("localhost", 3000)
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
// needing certificates.
.usePlaintext()
.build();
blockingStub = carParkServiceGrpc.newBlockingStub(channel);
asyncStub = carParkServiceGrpc.newStub(channel);
logger.info("Will try to get CarPark " + id + " ...");
CarParkToUpdateRequest request = CarParkToUpdateRequest.newBuilder().setDeviceId(id).build();
carParkResponse response;
try {
response = blockingStub.setSpaces(request);
}catch(StatusRuntimeException e) {
logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
return;
}finally {
channel.shutdown();
}
logger.info("Carpark: " + response.getCarPark());
spacesArea.append(response.getCarPark().toString());
}
public void setFull(int id) {
channel =ManagedChannelBuilder.forAddress("localhost", 3000)
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
// needing certificates.
.usePlaintext()
.build();
blockingStub = carParkServiceGrpc.newBlockingStub(channel);
asyncStub = carParkServiceGrpc.newStub(channel);
logger.info("Will try to get CarPark " + id + " ...");
CarParkToUpdateRequest request = CarParkToUpdateRequest.newBuilder().setDeviceId(id).build();
carParkResponse response;
try {
response = blockingStub.setFull(request);
}catch(StatusRuntimeException e) {
logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
return;
}finally {
channel.shutdown();
}
logger.info("Carpark: " + response.getCarPark());
fullArea.append(response.getCarPark().toString());
}
These two methods are supposed to send a request to the server to change the status of the 'car park' so if I send a request with setFull I get a response saying the carpark is full etc.
These are the methods from the server:
public void setSpaces(CarParkToUpdateRequest request, StreamObserver<carParkResponse> rStreamObserver) {
ArrayList<CarParkOperations.proto.cp.CarPark> carList = Car.getInstance();
for(int i=0; i<carList.size(); i++) {
if(carList.get(i).getCarParkId() == request.getDeviceId()) {
CarParkOperations.proto.cp.CarPark heater_rec = (CarParkOperations.proto.cp.CarPark) carList.get(i);
Car.carparkCar.clear();
Car.carparkCar.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(heater_rec.getCarParkId()).setLocation(heater_rec.getLocation()).setStatus("Spaces").build());
}
}
for(CarParkOperations.proto.cp.CarPark heater : Car.carparkCar) {
carParkResponse response = carParkResponse.newBuilder().setCarPark(heater).build();
rStreamObserver.onNext(response);
rStreamObserver.onCompleted();
return;
}
}
public void setFull(CarParkToUpdateRequest request, StreamObserver<carParkResponse> rStreamObserver) {
ArrayList<CarParkOperations.proto.cp.CarPark> carList = Car.getInstance();
for(int i=0; i<carList.size(); i++) {
if(carList.get(i).getCarParkId() == request.getDeviceId()) {
CarParkOperations.proto.cp.CarPark heater_rec = (CarParkOperations.proto.cp.CarPark) carList.get(i);
Car.carparkCar.clear();
Car.carparkCar.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(heater_rec.getCarParkId()).setLocation(heater_rec.getLocation()).setStatus("Full").build());
}
}
for(CarParkOperations.proto.cp.CarPark heater : Car.carparkCar) {
carParkResponse response = carParkResponse.newBuilder().setCarPark(heater).build();
rStreamObserver.onNext(response);
rStreamObserver.onCompleted();
return;
}
}
I think it's most likely something to do with the server methods but cant seem to figure it out.
This is where I am storing the data:
package CarParkOperations.proto.cp;
import java.util.ArrayList;
import com.google.rpc.Status;
public class Car extends ArrayList<CarPark>{
public static Car carparkCar;
public static Car getInstance() {
if(carparkCar == null) {
carparkCar = new Car();
}
return carparkCar;
}
public Car() {
this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(1).setStatus("Full").setLocation("Behind Building 1").build());
this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(2).setStatus("Full").setLocation("Behind Building 1").build());
this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(3).setStatus("Full").setLocation("Behind Building 4").build());
this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(4).setStatus("Full").setLocation("Behind Building 3").build());
this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(5).setStatus("Full").setLocation("Behind Building 2").build());
this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(6).setStatus("Full").setLocation("Behind Building 1").build());
this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(7).setStatus("Full").setLocation("Behind Building 1").build());
this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(10).setStatus("Full").setLocation("Behind Building 6").build());
this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(11).setStatus("Full").setLocation("Behind Building 1").build());
this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(12).setStatus("Spaces").setLocation("Behind Building 1").build());
this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(13).setStatus("Spaces").setLocation("Behind Building 1").build());
this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(14).setStatus("Spaces").setLocation("Behind Building 1").build());
}
}
Any suggestions would be much appreciated.
答案1
得分: 0
你可能需要同步Car.getInstance()方法,因为如果没有适当的同步,如果被不同的线程调用,它可能会意外地返回不同的实例!
public static synchronized Car getInstance() {
if(carparkCar == null) {
carparkCar = new Car();
}
return carparkCar;
}
另外,你的Car类不是线程安全的,因为它扩展了ArrayList,而ArrayList不是线程安全的。你应该让你的Car类扩展类似ConcurrentLinkedQueue这样的类,或者让你的Car类组合一个使用synchronizedList(new ArrayList<Object>())
的列表字段,而不是扩展ArrayList。
英文:
You might need synchronize Car.getInstance() method, because without proper synchronization, if it is called by different threads it may surprisingly return different instances!
public static synchronized Car getInstance() {
if(carparkCar == null) {
carparkCar = new Car();
}
return carparkCar;
}
Also your Car class is not thread-safe because it extends ArrayList which is not thread-safe. You should let your Car class extend something like ConcurrentLinkedQueue instead, or let your Car class compose a field of list = Collections.synchronizedList(new ArrayList<Object>()) instead of extending ArrayList.
专注分享java语言的经验与见解,让所有开发者获益!
评论