I work in java8 and would like to use class java.time.Duration to set up sleep time.
As I understand Duration is composed via seconds and nanoseconds.
So waiting Duration time is should be equivalent to waiting:
java.util.concurrent.TimeUnit.SECONDS.sleep(long);
java.util.concurrent.TimeUnit.NANOSECONDS.sleep(long);
Is my understating is correct?
The TimeUnit.sleep functionality only provides millisecond granularity for sleeping. It forwards to Thread.sleep and the nanoseconds are ignored.
public static void sleep(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
sleep(millis);
}
If you want something more reliable have a look at LockSupport.parkNanos. You should be able to get something like 50us granularity on your sleep on Linux.
https://hazelcast.com/blog/locksupport-parknanos-under-the-hood-and-the-curious-case-of-parking/
Related
I read about the problem a day ago where the problem occurs with people but when it comes to the final second. I kept noticing in my timer that the as it counts down it sometimes skips a second, some suggested changing the interval from 1000ms to 500ms others said make it 900. And there are those who suggested making your own Timer.
My timer is a bit big as it contains two smaller timers within it, that count down individual minutes within the total time and I activate an animation during those times. So basically I am asking what approach should I take to for a time critical counter that is 100% accurate?
This is my code:
private void startTimer() {
Log.println(Log.ASSERT, "CHECK","Entered startTimer() method");
millisInFuture = mTimeLeftInMillis;
mCountDownTimer = new CountDownTimer(mTimeLeftInMillis, 900) {
#Override
public void onTick(long millisUntilFinished) {
mTimeLeftInMillis = millisUntilFinished;
updateCountDownText();
millisPassed = millisInFuture - mTimeLeftInMillis;
progress = (int) (millisPassed * 100 / millisInFuture);
pb.setProgress(progress);
pb2.setProgress(0);
pb3.setProgress(0);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Key: 60 sec
if (millisInFuture == 480000) {
if (millisPassed <= 60000 || (millisPassed > 180000 && millisPassed <= 240000) || (millisPassed > 300000 && millisPassed <= 360000 || (millisPassed > 420000 && millisPassed <= 480000))) {
// Animation animation = AnimationUtils.loadAnimation(tool1mode1.this, R.anim.fade_in);
// stepupimage.setAnimation(animation);
Log.println(Log.ASSERT,"CHECK","Check that the first if statement of key 60 is entered");
statusIfUp();
time_of_stage = (millisInFuture - millisPassed) % 60000;
progress2 = (int) (time_of_stage*100 / 60000);
Log.println(Log.VERBOSE,"CHECK","TIME OF STAGE = "+time_of_stage);
Log.println(Log.VERBOSE,"CHECK","progress2= "+progress2);
pb2.setProgress(progress2);
updateStageUpCount();
upArrowAnimation();
setflowrate();
}
}
#Override
public void onFinish() {
Toast.makeText(tool1mode1.this, "Done", Toast.LENGTH_SHORT).show();
avd2.stop(); avd3.stop();
try {
pb.setProgress(100); pb2.setProgress(0); pb3.setProgress(0);
stage_timer.setVisibility(View.INVISIBLE);
stage_timer.setVisibility(View.INVISIBLE);
progressBar.setVisibility(View.INVISIBLE);
progressBar2.setVisibility(View.INVISIBLE);
progressBar.setProgress(0);
progressBar2.setProgress(0);
progressBar.setTranslationY(60);
progressBar2.setTranslationY(60);
flow.setTranslationY(60);
animation1.cancel(); animation2.cancel();
//Vibration
if (Build.VERSION.SDK_INT >= 26) {
((Vibrator) getSystemService(VIBRATOR_SERVICE)).vibrate(VibrationEffect.createOneShot(150, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
((Vibrator) getSystemService(VIBRATOR_SERVICE)).vibrate(VibrationEffect.createWaveform(new long[]{150}, new int[]{VibrationEffect.EFFECT_CLICK}, -1));
}
}
catch (NullPointerException e) {
e.printStackTrace();
}
}
}.start();
}
So to summarize: I have a big timer and two small timers that count certain intervals within the larger timer. Now the CountDownTimer class that is provided by Android skips a second or two at times during the count down. I want to fix this problem and don't know how, I would have just rolled with it but unfortunately the one I'm making the app for requires it to be 100% accurate as the application is time critical.
Note: pb, pb2, pb3, are progress bars of the timers (1st is the big one, 2nd and 3rd alternate for the second timer)
I am trying to run a task periodically every 10 ms. Before executing the task, I want to check the consistency of clock_nanosleep. I took 10 values to check the time clock_nanosleep is sleeping, but they are varying in between 19-22 ms, which should be 10 ms.
I am running this thread with SCHED_FIFO, pri-98, with HRTimers enabled in Linux. Currently, I am using 3.14.29 Linux Kernel with RT Patch. Does clock_nanosleep require any extra configuration in Linux apart from HRTIMERS?
Below is the code snippet that I am running:
struct timespec arr[20];
while(1) {
clock_gettime(CLOCK_MONOTONIC,&check1);
if(i<20) {
arr[i].tv_sec = check1.tv_sec;
arr[i].tv_nsec = check1.tv_nsec;
++i;
}
check1.tv_nsec += p_CT->period;
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &check1, NULL);
clock_gettime(CLOCK_MONOTONIC,&check);
if(i<20) {
arr[i].tv_sec = check.tv_sec;
arr[i].tv_nsec = check.tv_nsec;
++i;
}
}
check return values of clock_gettime and clock_nanosleep. Maybe there was interruption by signal
run two sequenced clock_gettime and calculate average execution time of clock_gettime. I don't think that it will be around 9-12ms, but let's check
Code:
int r1 = clock_gettime(CLOCK_MONOTONIC,&check1);
int r2 = clock_gettime(CLOCK_MONOTONIC,&check);
if(i<20) {
arr[i].tv_sec = check1.tv_sec;
arr[i].tv_nsec = check1.tv_nsec;
++i;
}
if(i<20) {
arr[i].tv_sec = check.tv_sec;
arr[i].tv_nsec = check.tv_nsec;
++i;
}
printf("%d %d\n", r1, r2);
static double myconversion(string farenheitinput)
{
double temporary = 0;
try
{
double farenheit = double.Parse(farenheitinput);
temporary = farenheit;
}
catch
{
Console.Write("\nWrong! you must write a number");
}
double celsius = (temporary - 32) * 5 / 9;
return celsius;
}
public void Main(string[] args)
{
double celsius = 0;
do
{
Console.Write("\nWrite your temperature in farenheit: ");
string farenheitinput = (Console.ReadLine());
celsius = myconversion(farenheitinput);
if (celsius < 73)
{
Console.WriteLine("\nThat temperature is too cold");
}
else if (celsius > 77)
{
Console.WriteLine("\nThat temperature is too hot");
}
}
while ((celsius >= 73) && (celsius <= 77));
{
Console.WriteLine("\nThe temperature is perfect");
}
Console.Write("\nPress any key to close program...");
Console.ReadKey();
}
I'm using a method to convert farenheit to celsius.
Here's the code that I'm using for my loop and the method, when I debug it shows that double celsius = 87.7 if 190 farenheit is input by the user which is a false condition for while and the code should loop, however it doesn't and steps into the while code anyways and ends the loop. I have no idea what is causing it so I thought id come here to ask.
Loop Conditional Expressions:
The way loop conditionals work is they continue when they evaluate to true.
runs 0 or more times while true
while (boolean expression|reference == true) { // do stuff }
runs 1 or more times while true
do { // do stuff } while (boolean expression|reference == true);
In either case on the first false encountered the looping stops.
Solution
What you did:
do
{
// input stuff
}
while ((73 >= celsius) && (77 <= celsius));
{
Console.WriteLine("\nTemperaturen är perfekt");
}
should be:
do
{
// input stuff
} while (celsius < 73 || celsius > 77);
Console.WriteLine("\nTemperaturen är perfekt");
do you see the difference?
Better yet is to avoid the do/while construct completely.
while (celsius < 73 || celsius > 77)
{
// input stuff
}
Console.WriteLine("\nTemperaturen är perfekt");
You might be tempted to replace (celsius < 73 || celsius > 77) with something like (!(73 >= celsius && 77 <= celsius)) but do not do it.
Avoid negation logic if at all possible, even when you think the negative is more readable, trust me on this. That little ! is really hard to see sometimes. And even when it is, it takes a human brain more effort to think about !(true) and even more effort to think about !(false).
This is code to run automated blinds. However, it appears that there is some memory leak going on inside of loop as my program will not run. I am using XOBXOB to input data. Look below for where it really breaks.
void loop()
{
Serial.println("loop");
// New XOB request every 4 seconds (if previous response has been received)
if (lastResponseReceived && (abs(millis() - lastRequestTime) > 4*1000)) {
// if the connection has dropped, reconnect
while (!XOB.connected()) XOB.connect();
// Reset timer and response flags. Then, request "XOB" contents
lastResponseReceived = false;
lastRequestTime = millis();
Serial.println("requesting xob");
//enter name of XOB
XOB.requestXOB("XOB");
Serial.println("XOB requested!");
}
// Load response a character at a time when it is available.
// If loadStreamedResponse returns true, a completed response has been received
// Get the "switch" message from the XOB and turn the LED on/off
// NOTE: The message contents are returned with quotes. So, include them
// in the comparison statement.
// Serial.println("LSR: ");
// Serial.print(XOB.loadStreamedResponse());
This is where the loop does not run. It seems that the stream of data from XOBXOB cannot be stored and therefore loadStreamedResponse returns false.
if (!lastResponseReceived && XOB.loadStreamedResponse()) {
Serial.println("requesting reponse");
lastResponseReceived = true;
Serial.println("Get Xob Messages");
//Gets the string from value.
String str_value = XOB.getMessage("value");
Serial.println(str_value);
//Gets the string from switch
String str_switch = XOB.getMessage("switch");
Serial.println(str_switch);
String str_text = XOB.getMessage("text");
Serial.println(str_text);
//If time is not set, get the time from text xob.
if(time_set == false) {
Serial.println("setting time");
// insert code to parse time and set it from the text xob.
time_set = true;
}
// parse the hour from value and convert to minute for wake hour
String string_hour = str_value.substring(1,3);
int wake_hour = string_hour.toInt();
//Serial.println(wake_hour);
// parse minute from value and convert to int for wake minute
String string_minute = str_value.substring(3,5);
int wake_minute = string_minute.toInt();
// Serial.println(wake_minute);
// compare wake_minute and wake_hour with current time
// convert both to minutes for comparison
int wake_time = wake_minute + (60 * wake_hour);
int current_time = 738; //minute() + (hour() * 60);
Serial.println("checking wake condtions");
// rise up blinds slowly if the wake time is + or - 1 minute and if the blinds are closed.
if((wake_time == current_time || wake_time == (current_time - 1) || wake_time == (current_time + 1))
&& blinds_open == false ) {
Serial.println("Natural Wakeup");
rollup_blinds_slow();
blinds_open = true; // blinds should be open now.
}
// Check for opening up blinds condition. Blinds must be closed, to open them
Serial.println("Checking Open Condition");
if (str_switch.equalsIgnoreCase("\"ON\"") && blinds_open == false) {
Serial.println("Blinds Up");
rollup_blinds_fast();
blinds_open = true;
Serial.println(blinds_open);
}
Serial.println("Check closing condition");
// Check for closing blinds condition. Blinds must be closed, to open them
if (str_switch.equalsIgnoreCase("\"OFF\"") && blinds_open == true) {
Serial.println("Blinds down");
rolldown_blinds_fast();
blinds_open = false;
}
}
How can I calculate the time of acceleration to 100kmh?
Well, I registered a location listener when the !location.hasSpeed() is true store the time of location into a variable. When the speed is reach of the given speed in this case 100km/h (27.77 m/s) I substract from the spped of location and the result I divide by 1000.
Here is the "pseudo code"
#Override
public void onLocationChanged(Location currentLoc) {
// when stop reseted, when start reset again
if (isAccelerationLoggingStarted) {
if (currentLoc.hasSpeed() && currentLoc.getSpeed() > 0.0) {
// dismiss the time between reset to start to move
startAccelerationToTime = (double) currentLoc.getTime();
}
}
if (!currentLoc.hasSpeed()) {
isAccelerationLoggingStarted = true;
startAccelerationToTime = (double) currentLoc.getTime();
acceleration100 = 0.0;
}
if (isAccelerationLoggingStarted) {
if (currentLoc.getSpeed() >= 27.77) {
acceleration100 = (currentLoc.getTime() - startAccelerationToTime) / 1000;
isAccelerationLoggingStarted = false;
}
}
}
The main problem i see here, is that whenever the device is moving, startAccelerationToTime is reset. (The first if only checks whether there's movement; it doesn't check whether there's already a start time recorded.
I don't see where isAccelerationLoggingStarted is needed at all -- the speed, and the variables themselves, can be cleaned up a bit to make it clear what the next step should be.
Your pseudocode probably ought to look something like:
if speed is 0
clear start time
else if no start time yet
start time = current time
clear acceleration time
else if no acceleration time yet, and if speed >= 100 mph
acceleration time = current time - start time
In Java, that'd look like...
long startTime = 0;
double accelerationTime = 0.0;
#Override
public void onLocationChanged(Location currentLoc) {
// when stopped (or so slow we might as well be), reset start time
if (!currentLoc.hasSpeed() || currentLoc.getSpeed() < 0.005) {
startTime = 0;
}
// We're moving, but is there a start time yet?
// if not, set it and clear the acceleration time
else if (startTime == 0) {
startTime = currentLoc.getTime();
accelerationTime = 0.0;
}
// There's a start time, but are we going over 100 km/h?
// if so, and we don't have an acceleration time yet, set it
else if (accelerationTime == 0.0 && currentLoc.getSpeed() >= 27.77) {
accelerationTime = (double)(currentLoc.getTime() - startTime) / 1000.0;
}
}
Now, i'm not sure exactly how location listeners work, or how often they notify you when you're moving. So this may only semi work. In particular, onLocationChanged might not get called when you're not moving; you may need to request an update (perhaps via a "reset" button or something) or set certain params in order to trigger the stuff that happens when speed == 0.