I´m trying to set a volatile boolean variable, called accelerationCheck
, in other thread and retrieve its value from a "main thread". This variable has to be true if the acceleration is below -7 during at least 500ms if not, false. The thing is I'm getting sometimes true when it should be false and vice versa. Why do you think this is happening? The code below is contained in the "main thread", this main thread is executed every 30ms with an Executor
:
if(vehicleData.getVehicleAcceleration() < -7) {
if(this.accTimer == null) {
this.accTimer = new CustomTimer();
}
this.accTimer.start();
this.accelerationObserver = new Runnable() {
public void run() {
accTimer.stop();
if(accTimer.getElapsedMilliseconds() >= 500) {
accelerationCheck = true;
accTimer.stop();
accTimer.start();
}
}
};
this.executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(accelerationObserver, 0, 100, TimeUnit.MILLISECONDS);
}
else {
this.accelerationObserver = null;
this.executor = null;
this.accTimer.stop();
this.accTimer = null;
this.accelerationCheck = false;
}
CustomTimer class:
public class CustomTimer {
private final long nanoSecondsPerMillisecond = 1000000;
private long stopWatchStartTime = 0;
private long stopWatchStopTime = 0;
private boolean stopWatchRunning = false;
public void start() {
this.stopWatchStartTime = System.nanoTime();
this.stopWatchRunning = true;
}
public void stop() {
this.stopWatchStopTime = System.nanoTime();
this.stopWatchRunning = false;
}
public boolean isRunning() {
return this.stopWatchRunning;
}
public long getElapsedMilliseconds() {
long elapsedTime;
if (stopWatchRunning)
elapsedTime = (System.nanoTime() - stopWatchStartTime);
else
elapsedTime = (stopWatchStopTime - stopWatchStartTime);
return elapsedTime / nanoSecondsPerMillisecond;
}
}
Variable vehicleData
is an object of this class:
public class VehicleDataStore extends Thread implements VehicleDataValueListener{
private long yawRate = 32767;
private long lateralAcceleration = 161;
private long vehicleAcceleration = 161;
private long speed = 16383;
private double accelerationPedal = 0.0;
private double brakePressure = 0.0;
private int accelerationControl = 0;
private int driveDirection = 2;
// Lights
private boolean highBeam = false;
private boolean lowBeam = false;
private boolean dayTimeRunning = false;
private boolean reverseLight = false;
private boolean fogLight = false;
private boolean parkingLights = false;
// AcelerationControl
private boolean emergencyBrake = false;
private boolean collisionWarning = false;
private boolean speedLimiter = false;
private boolean acc = false;
private boolean cruiseControl = false;
private boolean brakeActivated = false;
private boolean gasPedalActivated = false;
private long curvature = 1023;
private int hazardLights;
// private double vehicleSpeedKM100 = 0.0;
private boolean turnLeft = false;
private boolean turnRight = false;
private int warningLights = 0;
private int vehicleRole = Activator.vehicleRole;
private int stationType = Activator.stationType;
private DatagramSocket socket;
InetAddress inetAddress;
private int etsiPort = 12346;
private boolean isRunning = false;
private boolean embarkationStatus = false;
private int ptActivationType = 0;
private byte[] ptActivationData = null;
private int dangerousGoods = 0;
private boolean ligthSirenLb = false;
private boolean ligthSirenS = false;
private int steeringWheel = 512;
private int brakePressure05;
private boolean emergencyServiceCan = false;
private VehicleDataService service;
public VehicleDataStore(VehicleDataService service) {
this.service = service;
registerListeners(service);
this.isRunning = true;
}
public void onVehicleDataChange(String name, Cell cell) {
if (name.equalsIgnoreCase("AccelerationPedal")) {
setAccelerationPedal(cell);
} else if (name.equalsIgnoreCase("VehicleAcceleration")) {
setVehicleAcceleration(cell);
} else if (name.equalsIgnoreCase("VehicleSpeed")) {
setVehicleSpeed(cell);
} else if (name.equalsIgnoreCase("DriveDirection")) {
setDriveDirection(cell);
setReverseLight(cell);
} else if (name.equalsIgnoreCase("YawRate")) {
setYawRate(cell);
} else if (name.equalsIgnoreCase("LateralAcceleration")) {
setLateralAcceleration(cell);
} else if (name.equalsIgnoreCase("BrakePressure")) {
setBrakePressure(cell);
} else if (name.equalsIgnoreCase("AccelerationControl")) {
setAccelerationControl(cell);
} else if (name.equalsIgnoreCase("LowBeam")) {
setLowBeam(cell);
} else if (name.equalsIgnoreCase("HighBeam")) {
setHighBeam(cell);
} else if (name.equalsIgnoreCase("HazardLigths")) {
setHazardLigths(cell);
} else if (name.equalsIgnoreCase("TurnLeft")) {
setTurnLeft(cell);
} else if (name.equalsIgnoreCase("TurnRight")) {
setTurnRight(cell);
} else if (name.equalsIgnoreCase("WarningLights")) {
setWarningLights(cell);
} else if (name.equalsIgnoreCase("SteeringWheel")) {
setSteeringWheel(cell);
} /*else if (name.equalsIgnoreCase("EmergencyService")) {
setEmergencyService(cell);
}*/
}
private void registerListeners(VehicleDataService vehicleDataService) {
HashMap<String, VehicleData> vehicleDataMap = vehicleDataService.getMapVehicleDatabyName();
if (vehicleDataMap.containsKey("AccelerationPedal")) {
VehicleData data = vehicleDataMap.get("AccelerationPedal");
data.addCellValueListener(this);
setAccelerationPedal(data.getVehicleDataCell());
}
if (vehicleDataMap.containsKey("VehicleAcceleration")) {
VehicleData data = vehicleDataMap.get("VehicleAcceleration");
data.addCellValueListener(this);
setVehicleAcceleration(data.getVehicleDataCell());
}
if (vehicleDataMap.containsKey("VehicleSpeed")) {
VehicleData data = vehicleDataMap.get("VehicleSpeed");
data.addCellValueListener(this);
setVehicleSpeed(data.getVehicleDataCell());
}
if (vehicleDataMap.containsKey("DriveDirection")) {
VehicleData data = vehicleDataMap.get("DriveDirection");
data.addCellValueListener(this);
setDriveDirection(data.getVehicleDataCell());
setReverseLight(data.getVehicleDataCell());
}
if (vehicleDataMap.containsKey("YawRate")) {
VehicleData data = vehicleDataMap.get("YawRate");
data.addCellValueListener(this);
setYawRate(data.getVehicleDataCell());
}
if (vehicleDataMap.containsKey("LateralAcceleration")) {
VehicleData data = vehicleDataMap.get("LateralAcceleration");
data.addCellValueListener(this);
setLateralAcceleration(data.getVehicleDataCell());
}
if (vehicleDataMap.containsKey("BrakePressure")) {
VehicleData data = vehicleDataMap.get("BrakePressure");
data.addCellValueListener(this);
setBrakePressure(data.getVehicleDataCell());
}
if (vehicleDataMap.containsKey("AccelerationControl")) {
VehicleData data = vehicleDataMap.get("AccelerationControl");
data.addCellValueListener(this);
setAccelerationControl(data.getVehicleDataCell());
}
if (vehicleDataMap.containsKey("LowBeam")) {
VehicleData data = vehicleDataMap.get("LowBeam");
data.addCellValueListener(this);
setLowBeam(data.getVehicleDataCell());
}
if (vehicleDataMap.containsKey("HighBeam")) {
VehicleData data = vehicleDataMap.get("HighBeam");
data.addCellValueListener(this);
setHighBeam(data.getVehicleDataCell());
}
if (vehicleDataMap.containsKey("HazardLigths")) {
VehicleData data = vehicleDataMap.get("HazardLigths");
data.addCellValueListener(this);
setHazardLigths(data.getVehicleDataCell());
}
if (vehicleDataMap.containsKey("TurnLeft")) {
VehicleData data = vehicleDataMap.get("TurnLeft");
data.addCellValueListener(this);
setTurnLeft(data.getVehicleDataCell());
}
if (vehicleDataMap.containsKey("TurnRight")) {
VehicleData data = vehicleDataMap.get("TurnRight");
data.addCellValueListener(this);
setTurnRight(data.getVehicleDataCell());
}
if (vehicleDataMap.containsKey("WarningLights")) {
VehicleData data = vehicleDataMap.get("WarningLights");
data.addCellValueListener(this);
setWarningLights(data.getVehicleDataCell());
}
if (vehicleDataMap.containsKey("SteeringWheel")) {
VehicleData data = vehicleDataMap.get("SteeringWheel");
data.addCellValueListener(this);
setSteeringWheel(data.getVehicleDataCell());
}
/*if (vehicleDataMap.containsKey("EmergencyService")) {
VehicleData data = vehicleDataMap.get("EmergencyService");
data.addCellValueListener(this);
setEmergencyService(data.getVehicleDataCell());
}*/
}
/*
private void setEmergencyService(Cell cell) {
int emergencyServiceInt = 0;
if (cell.getCellType() == CellType.StateDataCell) {
StateDataCell dataCell = (StateDataCell) cell;
emergencyServiceInt = (int) dataCell.getCellValue();
if (emergencyServiceInt == 1) {
this.emergencyServiceCan = true;
} else {
this.emergencyServiceCan = false;
}
Activator.println("EmergencyServiceCan: " emergencyServiceCan);
checkEmergency();
}
}
private void checkEmergency() {
if (emergencyServiceCan) {
Activator.println("Priority Activated");
setLigthSirenLb(true);
CanWriterThread.setStatus(1);
} else {
setLigthSirenLb(false);
CanWriterThread.setStatus(2);
}
}*/
// AccelerationPedal
private void setAccelerationPedal(Cell cell) {
if (cell.getCellType() == CellType.DataCell) {
DataCell dataCell = (DataCell) cell;
this.accelerationPedal = dataCell.getCellValue();
if (this.accelerationPedal > 0.0) {
setGasPedalActivated(true);
} else {
setGasPedalActivated(false);
}
Activator.println("AccPedal: " accelerationPedal);
}
}
// BrakePressure
private void setBrakePressure(Cell cell) {
if (cell.getCellType() == CellType.DataCell) {
DataCell dataCell = (DataCell) cell;
this.brakePressure = dataCell.getCellValue();
this.brakePressure05 = (int) (dataCell.getCellValue() / 0.5);
if (this.brakePressure > 0.0) {
setBrakeActivated(true);
} else {
setBrakeActivated(false);
}
Activator.println("BrakePressure: " brakePressure);
}
}
public int getBrakePressure() {
return this.brakePressure05;
}
// AccelerationControl
private void setAccelerationControl(Cell cell) {
if (cell.getCellType() == CellType.StateDataCell) {
StateDataCell dataCell = (StateDataCell) cell;
this.accelerationControl = (int) dataCell.getCellValue();
setSpeedLimiter(false);
setAcc(false);
setCruiseControl(false);
switch (this.accelerationControl) {
case 1:
setCruiseControl(true);
break;
case 2:
setSpeedLimiter(true);
break;
case 3:
setAcc(true);
break;
default:
break;
}
Activator.println("AccControl: " accelerationControl);
}
}
// VehicleSpeed
private void setVehicleSpeed(Cell cell) {
// 0.01ms
if (cell.getCellType() == CellType.DataCell) {
// Speed in Km/h
DataCell dataCell = (DataCell) cell;
// Change to 0.01 m/s
this.speed = (long) (dataCell.getCellValue() * 3.6);
// this.vehicleSpeedKM100 = dataCell.getCellValue() * 100;
if (this.speed < 0 || this.speed > 16382) {
this.speed = SpeedValue.unavailable;
this.curvature = CurvatureValue.unavailable;
} else {
setCurvature();
}
Activator.println("Speed: " this.speed);
}
}
public long getVehicleSpeed() {
return this.speed;
}
// VehicleAcceleration
private void setVehicleAcceleration(Cell cell) {
if (cell.getCellType() == CellType.DataCell) {
DataCell dataCell = (DataCell) cell;
// Acceleration in 0.1 m/s2
this.vehicleAcceleration = (long) (dataCell.getCellValue());
if (this.vehicleAcceleration < -160 || this.vehicleAcceleration > 160) {
this.vehicleAcceleration = 161;
}
Activator.println("VehicleAcc: " vehicleAcceleration);
}
}
public long getVehicleAcceleration() {
return this.vehicleAcceleration;
}
// YawRate
private void setYawRate(Cell cell) {
if (cell.getCellType() == CellType.DataCell) {
DataCell dataCell = (DataCell) cell;
// YawRate in 0.01 º/s
this.yawRate = (long) (dataCell.getCellValue());
if (this.yawRate < -32766 || this.yawRate > 32766) {
this.yawRate = 32767;
}
Activator.println("YawRate: " yawRate);
}
}
public long getYawRate() {
return this.yawRate;
}
private void setSteeringWheel(Cell cell) {
DataCell dataCell = (DataCell) cell;
this.steeringWheel = (int) (dataCell.getCellValue() / 1.5);
if (this.steeringWheel >= 511) {
this.steeringWheel = 511;
}
if (this.steeringWheel <= -511) {
this.steeringWheel = -511;
}
Activator.println("SteeringWheel: " steeringWheel);
}
public int getSteeringWheelAngle() {
return this.steeringWheel;
}
// LateralAcceleration
private void setLateralAcceleration(Cell cell) {
if (cell.getCellType() == CellType.DataCell) {
DataCell dataCell = (DataCell) cell;
this.lateralAcceleration = (long) (dataCell.getCellValue());
if (this.lateralAcceleration < -160 || this.lateralAcceleration > 160) {
this.lateralAcceleration = 161;
}
Activator.println("LatAcc: " lateralAcceleration);
}
}
public long getLateralAcceleration() {
return this.lateralAcceleration;
}
// Curvature
public long getCurvature() {
return this.curvature;
}
public void setCurvature() {
this.curvature = 1023;
if (this.speed > 0) {
double radius = (this.yawRate / this.speed) * (Math.PI / 180);
this.curvature = (long) (1 / radius) * 10000;
}
if (this.curvature < -1023) {
this.curvature = -1023;
}
if (this.curvature > 1022) {
this.curvature = 1022;
}
}
public boolean isHighBeam() {
return highBeam;
}
public void setHighBeam(boolean highBeam) {
this.highBeam = highBeam;
}
private void setHighBeam(Cell cell) {
int highBeamInt = 0;
if (cell.getCellType() == CellType.StateDataCell) {
StateDataCell dataCell = (StateDataCell) cell;
highBeamInt = (int) dataCell.getCellValue();
if (highBeamInt == 1) {
this.highBeam = true;
} else {
this.highBeam = false;
}
Activator.println("HighBeam: " highBeam);
}
}
// LowBeam
private void setLowBeam(Cell cell) {
int lowBeamInt = 0;
if (cell.getCellType() == CellType.StateDataCell) {
StateDataCell dataCell = (StateDataCell) cell;
lowBeamInt = (int) dataCell.getCellValue();
if (lowBeamInt == 1) {
this.lowBeam = true;
} else {
this.lowBeam = false;
}
Activator.println("LowBeam: " lowBeam);
}
}
public boolean isLowBeam() {
return this.lowBeam;
}
public boolean isDayTimeRunning() {
return dayTimeRunning;
}
public void setDayTimeRunning(boolean dayTimeRunning) {
this.dayTimeRunning = dayTimeRunning;
}
public boolean isReverseLight() {
return reverseLight;
}
public void setReverseLight(boolean reverseLight) {
this.reverseLight = reverseLight;
}
private void setReverseLight(Cell cell) {
int reverseLightInt = 0;
if (cell.getCellType() == CellType.StateDataCell) {
StateDataCell dataCell = (StateDataCell) cell;
reverseLightInt = (int) dataCell.getCellValue();
if (reverseLightInt == 1) {
this.reverseLight = true;
} else {
this.reverseLight = false;
}
Activator.println("ReverseLight: " reverseLight);
}
}
public boolean isFogLight() {
return fogLight;
}
public void setFogLight(boolean fogLight) {
this.fogLight = fogLight;
}
public boolean isParkingLights() {
return parkingLights;
}
public void setParkingLights(boolean parkingLights) {
this.parkingLights = parkingLights;
}
// DriveDirection
private void setDriveDirection(Cell cell) {
if (cell.getCellType() == CellType.StateDataCell) {
StateDataCell dataCell = (StateDataCell) cell;
int canDriveDirection = (int) dataCell.getCellValue();
this.driveDirection = canDriveDirection;
// switch (canDriveDirection) {
// case 0:
// this.driveDirection = 2;
// break;
// case 1:
// this.driveDirection = 0;
// break;
// case 2:
// this.driveDirection = 1;
// break;
// case 3:
// this.driveDirection = 2;
// break;
//
// default:
// break;
// }
Activator.println("DriveDirection: " driveDirection);
}
}
public final int getDriveDirection() {
return this.driveDirection;
}
// SpeedLimiter
public boolean isSpeedLimiter() {
return speedLimiter;
}
private void setSpeedLimiter(boolean speedLimiter) {
this.speedLimiter = speedLimiter;
}
// Acc
public boolean isAcc() {
return acc;
}
private void setAcc(boolean acc) {
this.acc = acc;
}
// CruiseControl
public boolean isCruiseControl() {
return cruiseControl;
}
private void setCruiseControl(boolean cruiseControl) {
this.cruiseControl = cruiseControl;
}
// BrakeActivated
public boolean isBrakeActivated() {
return brakeActivated;
}
private void setBrakeActivated(boolean brakeActivated) {
this.brakeActivated = brakeActivated;
}
// GasPedalActivated
public boolean isGasPedalActivated() {
return gasPedalActivated;
}
private void setGasPedalActivated(boolean gasPedalActivated) {
this.gasPedalActivated = gasPedalActivated;
}
public boolean isEmergencyBrake() {
return emergencyBrake;
}
public void setEmergencyBrake(boolean emergencyBrake) {
this.emergencyBrake = emergencyBrake;
}
public boolean isCollisionWarning() {
return collisionWarning;
}
public void setCollisionWarning(boolean collisionWarning) {
this.collisionWarning = collisionWarning;
}
// HazardLights
private void setHazardLigths(Cell cell) {
StateDataCell dataCell = (StateDataCell) cell;
this.hazardLights = (int) dataCell.getCellValue();
Activator.println("HazardLights: " hazardLights);
}
public boolean isHazardLights() {
boolean hazardLights = false;
if (this.hazardLights == 1) {
hazardLights = true;
}
return hazardLights;
}
// TurnRight
private void setTurnRight(Cell cell) {
// TODO Auto-generated method stub
StateDataCell dataCell = (StateDataCell) cell;
if ((int) (dataCell.getCellValue()) == 0) {
this.turnRight = false;
} else {
this.turnRight = true;
}
Activator.println("TurnRight: " turnRight);
}
public boolean isTurnRightActivated() {
return turnRight;
}
// TurnLeft
private void setTurnLeft(Cell cell) {
// TODO Auto-generated method stub
StateDataCell dataCell = (StateDataCell) cell;
if ((int) (dataCell.getCellValue()) == 0) {
this.turnLeft = false;
} else {
this.turnLeft = true;
}
Activator.println("TurnLeft: " turnLeft);
}
public boolean isTurnLeftActivated() {
return turnLeft;
}
// WarningLights
private void setWarningLights(Cell cell) {
// TODO Auto-generated method stub
StateDataCell dataCell = (StateDataCell) cell;
this.warningLights = (int) dataCell.getCellValue();
Activator.println("WarningLights: " warningLights);
}
public boolean isWarningLightsActivated() {
boolean warningLights = false;
if (this.warningLights == 1) {
warningLights = true;
}
return warningLights;
}
public int getVehicleRole() {
return vehicleRole;
}
public void setVehicleRole(int vehicleRole) {
this.vehicleRole = vehicleRole;
}
public int getStationType() {
return stationType;
}
public void setStationType(int stationType) {
this.stationType = stationType;
}
public boolean isEmbarkationStatus() {
return embarkationStatus;
}
public void setEmbarkationStatus(boolean embarkationStatus) {
this.embarkationStatus = embarkationStatus;
}
public int getPtActivationType() {
return ptActivationType;
}
public void setPtActivationType(int ptActivationType) {
this.ptActivationType = ptActivationType;
}
public byte[] getPtActivationData() {
return ptActivationData;
}
public void setPtActivationData(byte[] ptActivationData) {
this.ptActivationData = ptActivationData;
}
public int getDangerousGoods() {
return dangerousGoods;
}
public void setDangerousGoods(int dangerousGoods) {
this.dangerousGoods = dangerousGoods;
}
public boolean isLigthSirenLb() {
return ligthSirenLb;
}
public void setLigthSirenLb(boolean ligthSirenLb) {
this.ligthSirenLb = ligthSirenLb;
}
public boolean isLigthSirenS() {
return ligthSirenS;
}
public void setLigthSirenS(boolean ligthSirenS) {
this.ligthSirenS = ligthSirenS;
}
public void stopThread() {
this.isRunning = false;
if (this.socket != null) {
this.socket.close();
}
}
}
AccelerationChecker class code:
public class AccelerationChecker{
private long currentAcceleration;
private double startTime;
private double currentTime;
private double elapsedTime;
private boolean flag;
public AccelerationChecker() {
this.currentAcceleration = 0;
this.flag = false;
this.startTime = 0;
this.currentTime = 0;
}
public void handleAccelerationCheck(long newValue) {
if(newValue < -7) {
this.startTime = System.nanoTime();
this.currentTime = System.nanoTime();
this.elapsedTime = this.currentTime - this.startTime;
if(this.elapsedTime >= 500) {
this.flag = true;
}
else {
this.flag = false;
}
}
}
public boolean getFlag() {
return flag;
}
}
CodePudding user response:
Instead of doing scheduled checks from the threads a better solution would be to make a call from setVehicleAcceleration to e.g. AccelerationChecker.handleAccelerationChange(long newValue). In that class you can implement the check logic using timestamps and the boolean flag.
Hereby a draft implementation:
within VehicleDataStore
:
private VehicleDataService service;
private AccelerationChecker accelerationChecker; // field to store AccelerationChecker
public VehicleDataStore(VehicleDataService service, AccelerationChecker accelerationChecker) {
this.service = service;
this.accelerationChecker = accelerationChecker; // inject the AccelerationChecker
registerListeners(service);
this.isRunning = true;
}
...
// VehicleAcceleration
private void setVehicleAcceleration(Cell cell) {
if (cell.getCellType() == CellType.DataCell) {
DataCell dataCell = (DataCell) cell;
// Acceleration in 0.1 m/s2
long newValue = (long) (dataCell.getCellValue());
if (newValue < -160 || newValue > 160) {
newValue = 161;
}
if (this.vehicleAcceleration != newValue) {
this.vehicleAcceleration = newValue;
this.accelerationChecker.handleAccelerationChange(newValue); // notify AccelerationChecker about the changed value
}
Activator.println("VehicleAcc: " vehicleAcceleration);
}
}
AccelerationChecker
class:
public class AccelerationChecker {
private final static long THRESHOLD_VALUE = -7;
private final static long VALIDATION_TIME_MS = 500;
private long lastTimeBelowThreshold = Long.MAX_VALUE;
private long lastValue = Long.MAX_VALUE;
public boolean isAccelerationLongBelowThreshold() {
return (lastValue < THRESHOLD_VALUE && System.currentTimeMillis() - lastTimeBelowThreshold > VALIDATION_TIME_MS);
}
public void handleAccelerationChange(long newValue) {
if (newValue < THRESHOLD_VALUE) {
if (lastValue >= THRESHOLD_VALUE) {
lastTimeBelowThreshold = System.currentTimeMillis();
}
} else {
lastTimeBelowThreshold = Long.MAX_VALUE;
}
lastValue = newValue;
}
}
Just create an instance of AccelerationChecker
and pass it to VehicleDataStore
constructor. Then call accelerationChecker.isAccelerationLongBelowThreshold()
to get the result of the check.
CodePudding user response:
The thing is I'm getting sometimes true when it should be false and vice versa. Why do you think this is happening?
Your code is very complex and needs to be boiled down for SO to help with this. I would suggest that you add some System.out.println(...)
statements to the key parts of the code which may change its behavior (because System.out
is a synchronized class) but should show you that it is executing in a manner that you aren't expecting.
I see at least one place where you are mutating a unsynchronized class in multiple threads. The this.accTimer
is started by the thread running in the scheduled executor as well as the caller. This means that its method should be synchronized
most likely. Not sure if it is the source of your overall problem.
Without seeing a much shorter example, it is very hard to understand the thread architecture so that I can help more.
Oh and to be pedantic, the "main thread" is the thread that executes the main()
method. As soon as you run code in an executor it is a different thread.