方法继续运行并发送相同的信息,即使对于不同的请求grpc。

huangapple 未分类评论49阅读模式
英文:

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(&quot;localhost&quot;, 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(&quot;Will try to get CarPark &quot; + id + &quot; ...&quot;);
			 CarParkToUpdateRequest request = CarParkToUpdateRequest.newBuilder().setDeviceId(id).build();
			 carParkResponse response;
			 try {
				 response = blockingStub.setSpaces(request);
			 }catch(StatusRuntimeException e) {
				 logger.log(Level.WARNING, &quot;RPC failed: {0}&quot;, e.getStatus());
			      return;
			 }finally {
					channel.shutdown();
				}
			 logger.info(&quot;Carpark: &quot; + response.getCarPark());
			 spacesArea.append(response.getCarPark().toString());
	 }

	 public void setFull(int id) {
		  channel =ManagedChannelBuilder.forAddress(&quot;localhost&quot;, 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(&quot;Will try to get CarPark &quot; + id + &quot; ...&quot;);
			 CarParkToUpdateRequest request = CarParkToUpdateRequest.newBuilder().setDeviceId(id).build();
			 carParkResponse response;
			 try {
				 response = blockingStub.setFull(request);
			 }catch(StatusRuntimeException e) {
				 logger.log(Level.WARNING, &quot;RPC failed: {0}&quot;, e.getStatus());
			      return;
			 }finally {
				channel.shutdown();
			 }
			 logger.info(&quot;Carpark: &quot; + 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&lt;carParkResponse&gt; rStreamObserver) {
    	ArrayList&lt;CarParkOperations.proto.cp.CarPark&gt; carList = Car.getInstance();
        for(int i=0; i&lt;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(&quot;Spaces&quot;).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&lt;carParkResponse&gt; rStreamObserver) {
    	ArrayList&lt;CarParkOperations.proto.cp.CarPark&gt; carList = Car.getInstance();
        for(int i=0; i&lt;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(&quot;Full&quot;).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&lt;CarPark&gt;{
	
	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(&quot;Full&quot;).setLocation(&quot;Behind Building 1&quot;).build());
		this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(2).setStatus(&quot;Full&quot;).setLocation(&quot;Behind Building 1&quot;).build());
		this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(3).setStatus(&quot;Full&quot;).setLocation(&quot;Behind Building 4&quot;).build());
		this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(4).setStatus(&quot;Full&quot;).setLocation(&quot;Behind Building 3&quot;).build());
		this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(5).setStatus(&quot;Full&quot;).setLocation(&quot;Behind Building 2&quot;).build());
		this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(6).setStatus(&quot;Full&quot;).setLocation(&quot;Behind Building 1&quot;).build());
		this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(7).setStatus(&quot;Full&quot;).setLocation(&quot;Behind Building 1&quot;).build());
		this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(10).setStatus(&quot;Full&quot;).setLocation(&quot;Behind Building 6&quot;).build());
		this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(11).setStatus(&quot;Full&quot;).setLocation(&quot;Behind Building 1&quot;).build());
		this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(12).setStatus(&quot;Spaces&quot;).setLocation(&quot;Behind Building 1&quot;).build());
		this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(13).setStatus(&quot;Spaces&quot;).setLocation(&quot;Behind Building 1&quot;).build());
		this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(14).setStatus(&quot;Spaces&quot;).setLocation(&quot;Behind Building 1&quot;).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.

huangapple
  • 本文由 发表于 2020年4月5日 00:07:47
  • 转载请务必保留本文链接:https://java.coder-hub.com/61030898.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定