I'm trying to get the user's speed 10 times in three seconds when a function is called, and then calculate the sum of all the gotten values. I have the global variable:
lateinit var fusedLocationProviderClient : FusedLocationProviderClient
Which I then initialize in the onCreate method like this:
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
And then this is the code where I try to calculate the sum of the speeds:
val task = fusedLocationProviderClient.lastLocation
var sumSpeed = 0F
task.addOnSuccessListener {
if (it != null) {
for (i in 1..10) {
Thread.sleep(300)
sumSpeed += it.speed
}
}
current_gps_speed_tv.text = "Total is: $sumSpeed"
if (sumSpeed < 25) {
...
}
}
The result of sumSpeed always remains the same (34m/s), which is 10 times it.speed, which is also the same every time (3.4m/s).
I've searched for other answers (like this one) but what I'm using seems to be different. Why does this happen? Thank you.
This won't work for at least a few different reasons.
You're trying to poll it more than once per second. I think the fastest rate position is updated is at best once per second, and it's going to depend on device.
You are simply adding the same value to the sum 10 times and sleeping the thread pointlessly. Calling sleep pauses execution of your code. It does not magically change the value of it to some new value polled from the GPS.
Calling Thread.sleep on the main thread will freeze your app.
You are polling lastLocation, which is some location already known from the last time the GPS was used. It only reports a single value that comes from the past. It cannot report multiple new values. Your success listener is called only one time, because either the last location is available or it's not.
To get multiple locations over a period of time, you need to use requestLocationUpdates instead of lastLocation. See here for the documentation.
Edit, to expand on 2 based on your comment:
Imagine this code:
val x = 5
var sum = 0
for (i in 0..9) {
sum = sum + 5
}
println(sum)
This adds the value of x to sum 10 times, so the result will be 50.
Now consider this code:
val x = 5
var sum = 0
for (i in 0..9) {
Thread.sleep(100)
sum = sum + 5
}
println(sum)
This code has the exact same result. It just takes a lot longer to return because it keeps pausing to sleep. Sleeping has no effect on the value of x. x is always the same value. The same is true of it in your code. There is only ever one instance of it in your function.
Related
I am currently creating a program to check the order status (pending or confirmed) when a user open the app now the problem is if I need to check after order time and between I am checking time (Current Time) in this timeframe check for how many times I change price and compare if price is match or not.
So how can I check a step before i. like i is 3 and I need to also include 2 in it and compare value of i and i+1 value in every loop without getting index out of bond.
Code :
for (i in 0 until arrTriple!!.size){
if (arrTriple[i].third >= ordertime){ //arrTriple[i].third is time when when I change price
//Need this value also without getting indexoutofbond = arrTriple[i+1].third
//So I can use my logic here.
}
}
Think I understand what you're asking. Can you start with i = to 1 and do i-1 instead of i+1? Something like this:
for (i in 1 until arrTriple!!.size) {
if (arryTriple[i-1].third >= overtime {
arrTriple[i].third
}
}
You'll have an edge case where arrTriple.size == 1 that you'd need to handle still.
EDIT:
Otherwise, just add an if-check.
for (i in 0 until arrTriple!!.size){
if (arrTriple[i].third >= ordertime && (i+1) < arrTriple.size){
}
}
You don't necessarily need until. You would write it just like this
for(element in arrTriple!!){
if(element.third >= ordertime){
// Your logic here
}
}
This would be my approach
I researched online and saw that Location Manager.requestLocationUpdates method and saw that it took an argument of minDistance. The definition that the site(http://blog.doityourselfandroid.com/2010/12/25/understanding-locationlistener-android/) gave me for that argument was "minimum distance interval for notifications" with an example of 10 meters. Can anyone clarify what that means? Everytime i move 10 meters with a phone, i get an gps update?
Yes, essentially this means that if the platform observes your current position as being more than minDistance from the last location that was saved by the platform, your listener will get notified with the updated position. Note that these two positions don't necessarily need to be sequential (i.e., there could be a number of small displacements that eventually add up to minDistance, and the location that finally exceeds the threshold will be the one reported to the app).
The actual platform code can be seen on Github, which I've also pasted below:
private static boolean shouldBroadcastSafe(
Location loc, Location lastLoc, UpdateRecord record, long now) {
// Always broadcast the first update
if (lastLoc == null) {
return true;
}
// Check whether sufficient time has passed
long minTime = record.mRequest.getFastestInterval();
long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
/ NANOS_PER_MILLI;
if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
return false;
}
// Check whether sufficient distance has been traveled
double minDistance = record.mRequest.getSmallestDisplacement();
if (minDistance > 0.0) {
if (loc.distanceTo(lastLoc) <= minDistance) {
return false;
}
}
...
Note that minDistance parameter only affects when your app gets notified if the value is greater than 0.
Also please be aware that with all positioning systems there is a significant level of error when calculating locations, so with small minDistance values you may get notified frequently, but these notifications may be error in positioning calculations, not true user movement.
I am trying to measure the performance of our service by putting the data in a HashMap like-
X number of calls came back in Y ms. Below is my code which is very simple. It will set the timer before hitting the service and after the response came back, it will measure the time.
private static void serviceCall() {
histogram = new HashMap<Long, Long>();
keys = histogram.keySet();
long total = 10;
long runs = total;
while (runs > 0) {
long start_time = System.currentTimeMillis();
// hitting the service
result = restTemplate
.getForObject("Some URL",String.class);
long difference = (System.currentTimeMillis() - start_time);
Long count = histogram.get(difference);
if (count != null) {
count++;
histogram.put(Long.valueOf(difference), count);
} else {
histogram.put(Long.valueOf(difference), Long.valueOf(1L));
}
runs--;
}
for (Long key : keys) {
Long value = histogram.get(key);
System.out.println("SERVICE MEASUREMENT, HG data, " + key + ":" + value);
}
}
Currently the output I am getting is something like this-
SERVICE MEASUREMENT, HG data, 166:1
SERVICE MEASUREMENT, HG data, 40:2
SERVICE MEASUREMENT, HG data, 41:4
SERVICE MEASUREMENT, HG data, 42:1
SERVICE MEASUREMENT, HG data, 43:1
SERVICE MEASUREMENT, HG data, 44:1
which means is 1 call came back in 166 ms, 2 calls came back in 40 ms and same with other outputs.
Problem Statement:-
What I am looking for now is something like this. I should have range setup like this-
X Number of calls came back in between 1 and 10 ms
Y Number of calls came back in between 11 and 20 ms
Z Number of calls came back in between 21 and 30 ms
P Number of calls came back in between 31 and 40 ms
T number of calls came back in between 41 and 50 ms
....
....
I number of calls came back in more than 100 ms
And any way to configure the range also. Suppose in future I need to tweak in the range, I should be able to do it. How can I achieve this thing in my current program? Any suggestions will be of great help.
A histogram is a set of data arranged into "bins" of equal size. You should convert your time measurement to a bin and use that bin as the map key. This can be done simply by dividing your time value by the bin size. For example: time / 10L.
In my current project, I am going to write a function of calculating average Temperature.
A notatable point of this function is that it receives data from many temperature sources at different time. Could you advise me "How can I write a function with such a behavior?"
For instance, following function receives tempSensorData from many temperature Sensors, which sends temperature data at different time. I need to write a logic of calculating average temperature.
public void calculateRoomAvgTemp(TempStruct tempSensorData) {
// Write logic of calculating Average Temperature.
}
Why don't you just keep a running average? Assuming that your method gets called each time a temperature reading is taken, you can do the following:
private final List<Double> temps = Collections
.synchronizedList(new ArrayList<Double>());
private double currentAverage = 0d;
public void calculateRoomAvgTemp(TempStruct tempSensorData) {
synchronized (this.temps) {
this.temps.add(tempSensorData.temp);
this.currentAverage = 0d;
for (Double temp : this.temps) {
this.currentAverage += temp;
}
this.currentAverage /= this.temps.size();
}
}
can you store past temperatures in a separate field in the class? I noticed that your method is void, therefore doesn't return anything. I'm going to assume you want to store the average in the separate field. Example:
public class TempCalculator {
private double totalTemp = 0;
private int sensors = 0;
private double averageTemp = 0;
public void calculateRoomAvgTemp(TempStruct tempSensorData) {
totalTemp += tempSensorData.getTemp(); // Assuming getTemp() exists
sensors += 1;
averageTemp = totalTemp / sensors;
}
public double getAvgTemp() {
return averageTemp;
}
}
Of course, this can be done with a list if you want to store temperatures used and shaped to your needs. Hope this helps.
one way I could think of - insert values as you receive them into an ArrayList. If you need to calculate the average temperature after each data point that you receive, run through a for loop and average out the data points in the ArrayList to get the required value. One could look into using memoization to avoid running through the loop for all values.
Another option would be to use apache commons math whereby you can use the descriptive statistics option (using a rolling array) to get the mean (average).
I am assuming your code is single threaded. If multithreaded, you could use a thread safe vector (or add locks/synchronization on your own).
Hope this helps.
To calculate the average without keeping all historic values in memory (or a database), use a "moving average". This mathematical tool can give you the new average from the last one plus the current value.
You can create one thread which will calculate the temperature and many which will measure it values from different places. When some measurement is done the thread pushes the result into e.g. LinkedBlockingQueue. It's important to synchronize this operation because many threads might try to push results at the same time. The thread which calculate average temperature would run in a loop, pop new result from the queue, recalculate the temperature and then once again try to pop another result. As far as the queue will be empty the thread would be blocked on reading from it. In this way you would have an asynchronous communication between threads and the average temperature would be recalculated immediately after the measurements are done.
I need to implement global object collecting statistics for web server. I have Statistics singleton, which has method addSample(long sample), which subsequently call updateMax. This has to be obviously thread-safe. I have this method for updating maximum of whole Statistics:
AtomicLong max;
private void updateMax(long sample) {
while (true) {
long curMax = max.get();
if (curMax < sample) {
boolean result = max.compareAndSet(curMax, sample);
if (result) break;
} else {
break;
}
}
}
Is this implementation correct? I am using java.util.concurrent, because I believe it would be faster than simple synchronized. Is there some other / better way to implement this?
As of Java 8, LongAccumulator has been introduced.
It is advised as
This class is usually preferable to AtomicLong when multiple threads
update a common value that is used for purposes such as collecting
statistics, not for fine-grained synchronization control. Under low
update contention, the two classes have similar characteristics. But
under high contention, expected throughput of this class is
significantly higher, at the expense of higher space consumption.
You can use it as follows:
LongAccumulator maxId = new LongAccumulator(Long::max, 0); //replace 0 with desired initial value
maxId.accumulate(newValue); //from each thread
I think it's correct, but I'd probably rewrite it a little for clarity, and definitely add comments:
private void updateMax(long sample) {
while (true) {
long curMax = max.get();
if (curMax >= sample) {
// Current max is higher, so whatever other threads are
// doing, our current sample can't change max.
break;
}
// Try updating the max value, but only if it's equal to the
// one we've just seen. We don't want to overwrite a potentially
// higher value which has been set since our "get" call.
boolean setSuccessful = max.compareAndSet(curMax, sample);
if (setSuccessful) {
// We managed to update the max value; no other threads
// got in there first. We're definitely done.
break;
}
// Another thread updated the max value between our get and
// compareAndSet calls. Our sample can still be higher than the
// new value though - go round and try again.
}
}
EDIT: Usually I'd at least try the synchronized version first, and only go for this sort of lock-free code when I'd found that it was causing a problem.
With Java 8 you can take advantage of functional interfaces and a simple lamda expression to solve this with one line and no looping:
private void updateMax(long sample) {
max.updateAndGet(curMax -> (sample > curMax) ? sample : curMax);
}
The solution uses the updateAndGet(LongUnaryOperator) method. The current value is contained in curMax and using the conditional operator a simple test is performed replacing the current max value with the sample value if the sample value is greater than the current max value.
as if you didn't have your pick of answers, here's mine:
// while the update appears bigger than the atomic, try to update the atomic.
private void max(AtomicDouble atomicDouble, double update) {
double expect = atomicDouble.get();
while (update > expect) {
atomicDouble.weakCompareAndSet(expect, update);
expect = atomicDouble.get();
}
}
it's more or less the same as the accepted answer, but doesn't use break or while(true) which I personally don't like.
EDIT: just discovered DoubleAccumulator in java 8. the documentation even says this is for summary statistics problems like yours:
DoubleAccumulator max = new DoubleAccumulator(Double::max, Double.NEGATIVE_INFINITY);
parallelStream.forEach(max::accumulate);
max.get();
I believe what you did is correct, but this is a simpler version that I also think is correct.
private void updateMax(long sample){
//this takes care of the case where between the comparison and update steps, another thread updates the max
//For example:
//if the max value is set to a higher max value than the current value in between the comparison and update step
//sample will be the higher value from the other thread
//this means that the sample will now be higher than the current highest (as we just set it to the value passed into this function)
//on the next iteration of the while loop, we will update max to match the true max value
//we will then fail the while loop check, and be done with trying to update.
while(sample > max.get()){
sample = max.getAndSet(sample);
}
}