Changing timer interval dynamically in Java 1.4 - timer

I have a timer task as shown below:
long timerSec = 5000;
TimerTask task1 = new TimerTask()
{
public void run()
{
//Some code...
System.out.println("Timer task...");
}
};
And a timer object as shown below:
Timer readFileTimer = new Timer();
I scheduled a task with 5 secs period between two successive task executions.
readFileTimer.scheduleAtFixedRate(task1, 0, timerSec);
Below line of code assigns new time period. I want to change the time period from 5 secs to n-secs (lets say 10 secs w.r.t. timerSec value).
timerSec = CalculateTimeForUpgrade(); //Get new timer interval period.
I tried below code, but didn't get the expected result.
readFileTimer.scheduleAtFixedRate(task1, 0, timerSec);
Please help. Thanks in advance.

Instead of starting the task at a fixed interval from the beginning, reschedule the task every time you finish it.
Something like this:
final Timer readFileTimer = new Timer();
readFileTimer.schedule(new MyTimerTask(), 0);
.......
private class MyTimerTask extends TimerTask() {
#Override
public void run() {
// Some code...
System.out.println("Timer task...");
if (readFileTimer!=null)
readFileTimer.schedule(new MyTimerTask(), CalculateTimeForUpgrade());
}
}

Related

Kotlin - press a button 1 time, show messages several times in TextView

How to implement showing several messages in a TextView field one by one with a required delay by clicking button only one time?
I tried this (look at the code below) and got such a result:
three seconds go by and only "3" is shown in the end. Digits 1 and 2 aren't shown.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.button.setOnClickListener {test()}
}
fun test() {
for (i in (1..3)){
binding.text1.text = "${i}"
Thread.sleep(1000L)
}
}
}
You really shouldn't sleep Main Thread. Main thread is used to display UI by sleeping it you are blocking the whole UI and that is why it is not updating. You can use Timer to run code every second
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//your method
}
}, 0, 1000);//1 second
So for example you can start timer on button click and stop it after 3 seconds
Thanks for the tip about Timer.
This thread helped me further.
How to create a simple countdown timer in Kotlin?
Now my code looks like this and it works and does what I wanted:
fun test() {
var cnt = 3
val timer = object: CountDownTimer(3000, 1000) {
override fun onTick(millisUntilFinished: Long) {
binding.text1.text = cnt.toString()
cnt--
}
override fun onFinish() {
binding.text1.text = "That's it"
}
}
timer.start()
}
Sleeping the main thread isn't solution for such simple task you should use concurrency like the code below using corouties
suspend fun test(){
for(i in (1..3) {
delay(1000L)
binding.text1.text = i.toStrong()
}
}
And invokeOnCompletion {} is pretty good callback to handle completion

Maximum time that an explicit wait can wait in selenium

My scenario is to wait for a particular element. It might take 2,3,4,5 days.
Can that be achieved using explicit wait or fluent wait?
If not what can be the maximum time we can give for explicit wait or fluent wait?
Use below code :-
int MINUTES = 1; // The delay in minutes
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() { // Function runs every MINUTES minutes.
YOURFUNCTIONNAME();
}
}, 0, 1000 * 60 * MINUTES);
Add the time as per your requirement

consitant interval timer (runnable results not sufficient)

We want to code a very accurate and consistent timer interval (100ms) to generate a periodic light pattern with the phone tourchlight.
Currently we use a runnable function, but this shows a lot of deviation.
If we measure the response with a photodiode we perceive deviations between 80 and even 150ms!
Is this error caused by the runnable function or the execution of the enable/disable of the Tourch function.
Below you can find the runnable that we used to trigger the phone tourchlight. The on/off period should be 100ms but is inconsistant variation of lenght and variation between on/off period. could this have to do with the camera service?
private final Runnable mRunnable = new Runnable() {
public void run() {
if (mActive) {
if (mSwap) {
mSwap = false;
mHander.postDelayed(mRunnable, 100);
params = camera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
} else {
mSwap = true;
mHander.postDelayed(mRunnable, 100);
params = camera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(params);
}
}
}
};
Please let us know if you need more information

Timer in Javafx Creating FX Thread null pointers and out of bounds exceptions

I was trying to make a simple timer in Javafx with a GUI and Timer class. When the start button is pressed, it is supposed to count down from the inputed time and stop when it reaches 0.
I have the remaining time in milliseconds updating in a TextField on the GUI but it only runs for a random number of milliseconds usually between 100-200 and then it freezes up and throws a VERY large number of exceptions.
I tried to pinpoint where the error was coming from, and found there was also a concurrent modification exception as well.
Here is my Timer class:
import java.sql.Time;
/**
* Created by Josh on 19/8/2015.
*/
public class Timer {
private long endTimeMillis;
public Timer(long hours, long minutes, long seconds){
long currentTime = System.currentTimeMillis();
endTimeMillis = ((seconds*1000 + minutes*1000*60 + hours*1000*60*60) + currentTime);
}
public boolean isFinished(){
long currentTime = System.currentTimeMillis();
if(endTimeMillis - currentTime <= 0){
return true;
}else{
return false;
}
}
public long getRemainingTimeMillis(){
long currentTime = System.currentTimeMillis();
return endTimeMillis - currentTime;
}
}
and this is the GUI
import javafx.application.Application;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
/**
* Created by Josh on 19/8/2015.
*/
public class GUI extends Application {
private BorderPane root;
Label hoursLabel, minutesLabel, secondsLabel;
TextField hoursTF, minutesTF, secondsTF;
Button startButton;
Label remainingTimeLabel;
TextField remainingTimeTF;
long remainingTime;
#Override
public void start(Stage primaryStage) throws Exception {
root = new BorderPane();
primaryStage.setScene(new Scene(root, 1300, 125));
primaryStage.show();
primaryStage.setResizable(true);
primaryStage.setTitle("Timer");
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent event) {
event.consume();
System.exit(0);
}
});
FlowPane center = new FlowPane();
hoursLabel = new Label(" Hours: ");
hoursTF = new TextField();
minutesLabel = new Label(" Minutes: ");
minutesTF = new TextField();
secondsLabel = new Label(" Seconds: ");
secondsTF = new TextField();
center.getChildren().addAll(hoursLabel, hoursTF, minutesLabel, minutesTF, secondsLabel, secondsTF);
root.setCenter(center);
FlowPane bottom = new FlowPane();
bottom.setAlignment(Pos.CENTER);
startButton = new Button("Start");
startButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
start();
}
});
remainingTimeLabel = new Label(" Time Remaining: ");
remainingTimeTF = new TextField();
bottom.getChildren().addAll(startButton, remainingTimeLabel, remainingTimeTF);
root.setBottom(bottom);
}
public void start(){
Task timer = new Task<Void>() {
#Override
protected Void call() throws Exception {
long hours = 0, minutes = 0, seconds = 0;
try{
if(hoursTF.getText() == null || hoursTF.getText().equals("")){
hours = 0;
}else{
hours = Long.parseLong(hoursTF.getText());
}
if(minutesTF.getText() == null || minutesTF.getText().equals("")){
minutes = 0;
}else{
minutes = Long.parseLong(minutesTF.getText());
}
if(secondsTF.getText() == null || secondsTF.getText().equals("")){
seconds = 0;
}else{
seconds = Long.parseLong(secondsTF.getText());
}
}catch(NumberFormatException e){
System.out.println("Error");
}
Timer timer = new Timer(hours, minutes, seconds);
while(!timer.isFinished()){
remainingTimeTF.setText(Long.toString(timer.getRemainingTimeMillis()));
}
return null;
}
};
new Thread(timer).start();
}
public static void main(String[] args) {
launch(args);
}
}
any help would be appreciated!
New stack trace:
x.beans.property.StringPropertyBase.set(StringPropertyBase.java:49)
at javafx.beans.property.StringProperty.setValue(StringProperty.java:65)
at javafx.scene.control.Labeled.setText(Labeled.java:145)
at GUI$3.call(GUI.java:109)
at GUI$3.call(GUI.java:80)
at javafx.concurrent.Task$TaskCallable.call(Task.java:1423)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.lang.Thread.run(Thread.java:745)
Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:204)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:438)
at javafx.scene.Parent$2.onProposedChange(Parent.java:364)
at com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:113)
at com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:108)
at com.sun.javafx.scene.control.skin.LabeledSkinBase.updateChildren(LabeledSkinBase.java:575)
at com.sun.javafx.scene.control.skin.LabeledSkinBase.handleControlPropertyChanged(LabeledSkinBase.java:204)
at com.sun.javafx.scene.control.skin.LabelSkin.handleControlPropertyChanged(LabelSkin.java:49)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase.lambda$registerChangeListener$61(BehaviorSkinBase.java:197)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$$Lambda$102/1442917786.call(Unknown Source)
at com.sun.javafx.scene.control.MultiplePropertyChangeListenerHandler$1.changed(MultiplePropertyChangeListenerHandler.java:55)
at javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:89)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:103)
at javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:110)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:144)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:49)
at javafx.beans.property.StringProperty.setValue(StringProperty.java:65)
at javafx.scene.control.Labeled.setText(Labeled.java:145)
at GUI$3.call(GUI.java:109)
at GUI$3.call(GUI.java:80)
at javafx.concurrent.Task$TaskCallable.call(Task.java:1423)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.lang.Thread.run(Thread.java:745)
You are violating the rule about not accessing the state of a node in a live scene graph on a background thread. Most JavaFX controls will actually check for this and throw an IllegalStateException when you do this: apparently TextInputControl.setText(...) doesn't (presumably for reasons of performance).
The simplest fix is to update the message property of the task:
while(!timer.isFinished()){
updateMessage(Long.toString(timer.getRemainingTimeMillis()));
// remainingTimeTF.setText(Long.toString(timer.getRemainingTimeMillis()));
}
(this causes an update to the message property to occur on the FX Application Thread), and then bind the text field's text property to it:
remainingTimeTF.textProperty().bind(timer.messageProperty());
new Thread(timer).start();
However, there are a lot of things about your code that violate good practice. Fo example, you should really compute the total time outside of the task (i.e. on the FX Application Thread) and store it in a final variable; and the busy while loop is pretty horrible (though updateMessage(...) will fix most of the issues associated with that for you).
I recommend you read up on multithreading in JavaFX. Start with the Task API docs. Maybe this question will help: Using threads to make database requests
First of all, if you really need to update that TextField in the way you are doing it I would recommend adding a Thread.sleep(100); (10 updates per second) in your while, or even Thread.sleep(1000); (1 update per second) since it's really CPU intensive to update that text field on every CPU cycle and usually you don't need to..
Secondly (and probably the reason of your exceptions) the call remainingTimeTF.setText(); MUST happen IN the FX Thread, try this code instead:
Platform.runLater(new Runnable() {
#Override public void run() {
remainingTimeTF.setText(Long.toString(timer.getRemainingTimeMillis()));
}
});
Right now you are setting the text outside the FX Thead which might lead to several exceptions since update requests are happening in a worker thread and the actual UI modifications are happening in the FX thread. You need to make sure that every time you need to modify the UI it happens in the correct thread, in this case the FX Thread with the Platform.runLater() call.
Also since you are already using the Task class why not bind the text property and use the updateMessage() or updateTitle() methods instead?
Take a look at this article, it has good examples for the correct usage of Task and updating the UI from worker threads.
Hope this helps!

DispatcherTimer for displaying seconds

I am trying to display a simple second counter. I have a dispatchertimer with a tick interval of 1 second and a textbox which I update in the tick handler with the current amount of seconds. There is a tiny amount of work in the tick handler, namely a call to 'tostring()' on some ints.
My issue is that the seconds are slower than they should be. Even if I set the interval to 100 milliseconds and make a check when elapsed, it is still slower than it should be. (over the course of a minute it is roughly 6 seconds slow).
Can anyone point me in the right direction for displaying a second counter that is accurate?
EDIT: Some code here (in .xaml.cs). It is taken from an example which works fine. The difference is that I am setting the Text property of a TextBox, rather than a Value property of another control.
...
this.timer.Interval = TimeSpan.FromMilliseconds(100);
...
private void OnDispatcherTimer_Tick(object sender, EventArgs e) {
if (this.currentValue > TimeSpan.Zero) {
this.currentValue = this.currentValue.Value.Subtract(TimeSpan.FromMilliseconds(100));
} else {
// stop timer etc
}
this.seconds.Text = this.currentValue.Value.Seconds.ToString();
}
Your way of keeping track of time is flawed. You're incrementing a counter each time the timer ticks, but there's no guarantee your timer will execute every 100 ms. And even if it did, you'd have to take into account the execution time of your code. Therefore, no matter what you do, your counter will drift.
What you must do is storing the date at which you started your counter. Then, every time the timer ticks, you compute the number of seconds that have elapsed:
private DateTime TimerStart { get; set; }
private void SomePlaceInYourCode()
{
this.TimerStart = DateTime.Now;
// Create and start the DispatcherTimer
}
private void OnDispatcherTimer_Tick(object sender, EventArgs e) {
var currentValue = DateTime.Now - this.TimerStart;
this.seconds.Text = currentValue.Seconds.ToString();
}
If you care about precise time a dispatchertimer is not good choice.
I thing you should separate counting seconds(time) and displaying on screen.
Use a System.Threading.Timer and use Dispatcher.BeginInvoke() in Timer callback.
simple example:
public partial class MainPage : PhoneApplicationPage
{
private DateTime _startDate;
private int _secondDuration;
private Timer _timer;
// Constructor
public MainPage()
{
InitializeComponent();
_startDate = DateTime.Now;
_secondDuration = 0;
_timer= new Timer(timerCallback, null, 0, 10);
}
private void timerCallback(object state)
{
var now = DateTime.Now;
if (now > _startDate + TimeSpan.FromSeconds(1))
{
_secondDuration += 1;
_startDate = now;
Dispatcher.BeginInvoke(() => { Counter.Text = _secondDuration.ToString(); });
}
}
}
After every 10 milisecond timer checks for one second has elapsed and print to textbox elapsed seconds
or you can do this like:
public partial class MainPage : PhoneApplicationPage
{
private Timer _timer;
private int _secondDuration;
// Constructor
public MainPage()
{
InitializeComponent();
_timer = new Timer(timerCallback, null, 0, 1000);
}
private void timerCallback(object state)
{
_secondDuration += 1;
Dispatcher.BeginInvoke(() => { Counter.Text = _secondDuration.ToString(); });
}
}

Resources