Java swing timer when delay is set to 0? - java

When the delay is set to 0, what is the interval for the listener to be called?
I tried changing delay to various values, but my listener was capped at about 60 times per second, unless I changed it to larger value like 100. Is 60 fps the defualt value? How can I increase the fps?
public class test {
static long previousTime;
public static void main(String[] args) {
Timer timer = new Timer(0, new ActionListener() {
public void actionPerformed(ActionEvent e) {
long currentTime = System.currentTimeMillis();
System.out.println((currentTime - previousTime) / 1000d);
previousTime = System.currentTimeMillis();
}
});
timer.start();
while (true);
}
}
This is the code I tested with. When delay is not big enough, it prints around 0.015.

Related

Making thread.sleep accurate

I am attempting to make a game loop that has an accurate timer. I know that TimeUnit uses thread.sleep(); which can vary by milliseconds. My question is simple:
Does this code make thread.sleep(); more accurate?
and further
Is there anything I can do to fix/make it better, or should I abandon it?
import java.util.concurrent.TimeUnit;
public class Timer implements Runnable {
public static void main(String[]args){
new Timer().start();
}
public int ups = 1;
#Override
public void run() {
int uc = 0;
long startTime = 0;
long result = 0;
long offset = 0;
while(true){
startTime = System.nanoTime();
uc++;
if(uc==1000/ups){
update();
uc=0;
}
result = System.nanoTime()-startTime;
if(1000000-result>0)
try {
int prefered = 1000000;
startTime = System.nanoTime();
TimeUnit.NANOSECONDS.sleep(prefered-result-offset);
offset = System.nanoTime()-startTime-prefered+result+offset;
} catch (InterruptedException e) {
System.out.println("an error has occured");
}
}
}
public void update(){
System.out.println("Hello World");
}
public void start(){
new Thread(this).start();
}
}
I have already seen this by the way. I might as well add
How does this compare to the other loop?
Edit: This is for a desktop game, not mobile
In case of games, I doubt you really want nanosecond precision in waking up. What you do want though is avoiding accumulating error, which is what your code is trying to do. It's a reasonable approach, although it probably would make more sense to use a Timer instead:
Timer timer = new Timer()
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Your periodic code here
}
}, 0, 1);

Making a stopwatch using timer for javafx

I actually have a video streaming application and I want to show the time for how much the two people have chatted with eachother. I have used Timer and TimerTask of java.util class but it gives error as "Not on FX application thread" which means I cant setText to a java fx component using swing thread. This is what I have tried so far:-
int timerx=0 //global variable
private void timer(){
/*SHOWING TIME PASSED*/
int x=0;
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
System.out.println("working");
setTime();
}
};
timer.schedule(timerTask, 50, 50);
}
And updating the javafx Label as:-
private void setTime(){
timerx = timerx +1;
Platform.runLater(new Runnable(){
public void run(){
time.setText(String.valueOf((timerx)));
System.out.println(time.getText());
}
});
}
I think the main problem is javafx component not being able to update and be accessed from swing thread. I would be glad to get any kind of help.
Thank you
You can use something like this:
long timeStart = System.currentTimeMillis();
when the chat start and get how long two guys chatted with something like this:
long timePassed = System.currentTimeMillis() - timeStart;
This will get you how many millisecond have passed. If you want to get second divide it by 1000. Oh and if you want it on thread, just create a thread for this thingy..
ok thank you all for your answers. I solved my problem by running a thread and using algorithm that will show the time in 00:00:00 format which I wanted to make. Here is the code
private void startTime(){
if(timerStats==false)
{
timerStats = true;
timer = new Timer();
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
System.out.println("working" + x);
timersec ++;
Platform.runLater(new Runnable(){
public void run(){
if (timersec == 60)
{
timersec = 0;
timermin++;
}
if (timermin == 60)
{
timermin = 0;
timerhr++;
}
String seconds = Integer.toString(timersec);
String minutes = Integer.toString(timermin);
String hours = Integer.toString(timerhr);
if (timersec <= 9)
{
seconds = "0" + Integer.toString(timersec);
}
if (timermin <= 9)
{
minutes = "0" + Integer.toString(timermin);
}
if (timerhr <= 9)
{
hours = "0" + Integer.toString(timerhr);
}
time.setText(hours + ":" + minutes +":"+ seconds);
System.out.println(time.getText());
}
});
}
};
timer.schedule(timerTask, 50, 50); //lastone is time, milli second
}
}
Thank you

Timer Task Only Runs Once

How do I make my Timer Task run more than once? This is really bothering me..
timer = new Timer();
timer.schedule(new Client(), 1000);
public void run() {
try {
System.out.println("sent data");
socketOut.write(0);
} catch (Exception e) {
// disconnect client on their side
Game.destroyGame();
timer.cancel();
timer.purge();
}
}
I want this timer to run for an infinite amount of time until the Exception occurs.
When the Javadoc says that it repeats with a specific delay, the delay is the initial delay before the TimerTask starts and not for how long the TimerTask will run. You can repeat the task every period milliseconds. Look at the schedule method. Below is a simple example that repeats every 2 seconds, indefinitely. In the example, the call:
timer.schedule(new RemindTask(seconds), 0, seconds * 1000);
tells timer to run the RemindTask every seconds seconds (*1000 because the time here is really in miliseconds), with an initial delay of 0 - i.e. start the RemindTask right away and then keep repeating at regular intervals.
import java.util.Timer;
import java.util.TimerTask;
public class Main {
static Timer timer;
static int i = 0;
class RemindTask extends TimerTask {
private int seconds;
public RemindTask(int seconds) {
this.seconds = seconds;
}
public void run() {
i+= seconds ;
System.out.println(i + " seconds!");
}
}
public Main(int seconds) {
timer = new Timer();
timer.schedule(new RemindTask(seconds), 0, seconds * 1000);
}
public static void main(String args[]) {
new Main(2);
System.out.format("Task scheduled.%n");
}
}
Looks like to me you're running a GUI program (I'm assuimg SWING, because your other question you were using SWING). So here's a bit of advice. Use a javax.swing.Timer for Swing program.
"How do I make my Timer Task run more than once? "
javax.swing.Timer has methods .stop() and .start() and .restart(). A basic implementation of the Timer object is something like this
Timer timer = new Timer(delay, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
// do something
}
});
timer.start();
You can do anything you want in the actionPerformed and it will fire an event every how many ever milliseconds you provide to the delay. You can have a button call .start() or .stop()
See this answer for a simple implementation of Timer imitating a sort of stop watch for a Boggle game

Making a program run for 5 minutes

So I wanted to try out something for a bit with the Timer and TimerTask classes.
I was able to get a line of code to execute after 30 seconds elapsed.
What I've been trying to do now is to get this line of code to execute for 5 minuets.
This is what I originally tried
public static void main(String[] args)
{
for ( int i = 0; i <= 10; i ++ )
{
Timer timer = new Timer();
timer.schedule( new TimerTask()
{
public void run()
{
System.out.println("30 Seconds Later");
}
}, 30000
);
}
}
I used the number 10 in the for loop to see if the timer.schedule would wait for another 30 seconds during the next iteration of the loop.
Any idea how I should go about this? I tried using the schedule method with a parameter passed in for period, but that only made it re-execute and it never stopped.
Java has provided a rich set of APIs in java.util.concurrent package to achieve such tasks. One of these APIs is ScheduledExecutorService. For example consider the code given below: This code will execute the Runnable task after every 30 seconds for upto 5 minutes:
import java.util.concurrent.*;
class Scheduler
{
private final ScheduledExecutorService service;
private final long period = 30;//Repeat interval
public Scheduler()
{
service = Executors.newScheduledThreadPool(1);
}
public void startScheduler(Runnable runnable)
{
final ScheduledFuture<?> handler = service.scheduleAtFixedRate(runnable,0,period,TimeUnit.SECONDS);//Will cause the task to execute after every 30 seconds
Runnable cancel = new Runnable()
{
#Override
public void run()
{
handler.cancel(true);
System.out.println("5 minutes over...Task is cancelled : "+handler.isCancelled());
}
};
service.schedule(cancel,5,TimeUnit.MINUTES);//Cancels the task after 5 minutes
}
public static void main(String st[])
{
Runnable task = new Runnable()//The task that you want to run
{
#Override
public void run()
{
System.out.println("I am a task");
}
};
Scheduler sc = new Scheduler();
sc.startScheduler(task);
}
}
The issue you're running into is that the scheduled Timer runs on a different thread - that is, the next iteration of your for loop starts running immediately after scheduling, not 30 seconds later. It looks like your code starts ten timers all at once, which means they should all print (roughly) 30 seconds later, all at once.
You were on the right track when you tried using the recurring version of schedule (with the third parameter). As you noted, this isn't quite what you want because it runs indefinitely. However, Timer does have a cancel method to prevent subsequent executions.
So, you should try something like:
final Timer timer = new Timer();
// Note that timer has been declared final, to allow use in anon. class below
timer.schedule( new TimerTask()
{
private int i = 10;
public void run()
{
System.out.println("30 Seconds Later");
if (--i < 1) timer.cancel(); // Count down ten times, then cancel
}
}, 30000, 30000 //Note the second argument for repetition
);
here's a workaround I'm ashamed of presenting:
package test;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class FiveMinutes {
private static int count = 0;
// main method just to add example
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
System.out.println("Count is: " + count);
if (count == 1) {
System.err.println("... quitting");
System.exit(0);
}
count++;
}
},
// starting now
new Date(),
// 5 minutes
300000l
);
}
}
Also please note that the application might not run exactly 5 minutes - see documentation for TimerTask.
Your solution is pretty close to working, you just have to multiply the delay by the counter (in your case, i):
public static void main(String[] args)
{
for (int i = 1; i <= 10; i++) // start i at 1 for initial delay
{
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run()
{
System.out.println("30 Seconds Later");
}
}, 30000 * i); // 5 second intervals
}
}
I don't know if this solution has problems with the garbage collector or not, but I throw it in here anyways. Maybe someone clears that out, and I learn something as well. Basically a timer sets a new timer if there is time left, and it should stop after 5 minutes.
Main.java:
public class Main {
public static void main(String[] args) {
MyTimer myTimer = new MyTimer(300000,30000);
myTimer.startTimer();
}
}
MyTimer.java:
import java.util.Timer;
import java.util.TimerTask;
public class MyTimer {
private int totalRunningTime;
private int currentTime = 0;
private int intervalTime;
private Timer timer = new Timer();
public MyTimer(int totalRunningTime, int intervalTime) {
this.totalRunningTime = totalRunningTime;
this.intervalTime = intervalTime;
}
public void startTimer() {
startTimer(intervalTime);
}
private void startTimer(int time) {
timer.schedule(new TimerTask() {
public void run() {
if (currentTime <= totalRunningTime - intervalTime) {
printTimeSinceLast(intervalTime / 1000);
currentTime += intervalTime;
startTimer(intervalTime);
} else if (currentTime < totalRunningTime) {
int newRestIntervalTime = totalRunningTime - currentTime;
printTimeSinceLast(newRestIntervalTime / 1000);
currentTime += newRestIntervalTime;
startTimer(newRestIntervalTime);
}
}
}, time);
}
private void printTimeSinceLast(int timeSinceLast) {
System.out.println(timeSinceLast + " seconds later.");
}
}

To calculate the total time elapsed using threads in java

I have this java code using Threads to calculate the time elapsed once the start button is hit till the stop button is not hit.
I want to do this using Threads only
import javax.swing.*;
import java.awt.event.*;
// This will count the elapsed time between running time of two threads.
class ThreadGame {
JButton button;
MyAction my_action;
public static void main(String[] args) {
ThreadGame tg = new ThreadGame();
}
public ThreadGame() {
JFrame frame = new JFrame("Calculate time - Game");
button = new JButton("Start");
button.addActionListener(new MyAction());
frame.add(button);
frame.setSize(400, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
class MyAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
String text = (String) e.getActionCommand();
final Timer timer = new Timer();
if (text.equals("Start")) {
button.setText("Stop");
Thread start_time = new Thread() {
public void run() {
timer.startTime();
}
};
start_time.start();
try {
start_time.join();
} catch (Exception e1) {
}
} else {
Thread stop_time = new Thread() {
public void run() {
timer.stopTime();
}
};
Thread get_time = new Thread() {
public void run() {
timer.getElapsedTime();
System.out.println(timer.elapsed);
}
};
stop_time.start();
try {
stop_time.join();
} catch (Exception e2) {
}
get_time.start();
button.setText("Start");
}
}
}
class Timer {
public double startTime = 0.0;
public double stopTime = 0.0;
public boolean running = false;
public double elapsed = 0.0;
public void startTime() {
this.startTime = System.nanoTime();
this.running = true;
}
public void stopTime() {
this.stopTime = System.nanoTime();
this.running = false;
}
// Elasped time in seconds
public double getElapsedTime() {
// double elapsed;
if (running) {
elapsed = ((System.nanoTime() - startTime) / 1000);
} else {
elapsed = ((stopTime - startTime) / 1000);
}
return elapsed;
}
}
}
EDIT: I have understand the problem: timer scope was the problem.
EDIT 2: Ok, it looks like I have to use suspend and resume in one thread only.
The problem is that the start button press is starting a different Timer object than the stop-button button press is stopping because the Timer object is created every time when the actionPerformed(...) method is called.
The Timer needs to be a field in your MyAction class. You also don't need all of the thread start/joins because the Timer object is very simple and fast.
Really, you can just use a startTimeMillis long field instead of a timer. Something like:
class MyAction implements ActionListener {
private long startTimeMillis;
public void actionPerformed(ActionEvent e) {
String text = (String) e.getActionCommand();
if (text.equals("Start")) {
startTimeMillis = System.currentTimeMillis();
...
} else {
System.out.println(System.currentTimeMillis() - startTimeMillis);
}
}
}
Your problem is caused by the scope of timer. This should be a private instance variable, not a local method variable. Further, wrapping calls to startTime and endTime in a thread's run method isn't gaining you anything, because these are incredibly short-lived calls. But that's not the real problem here.
There's no reason to be running Timer in its own thread. That is, without using a specialized real-time operating system, using threads to solve the problem of measuring the duration between two events is just plain wrong.
You might think that you could create a thread with a loop that increments a msec variable after a Thread.sleep(1). Don't do this! This kind of timing is also just plain wrong. Your computer uses a preemptive multitasking model which means there's no guarantee that your thread will execute on a regular interval. That is, there is nothing requiring that Thread.sleep(1) will sleep for some maximum duration. The guarantee is that your thread will sleep for a minimum of 1ms. This means there's no way to determine clock error if you're managing a clock yourself in software, and this error is not insignificant. Just don't do it!! Time should always be measured by your operating system, preferably using an interrupt-based timer (which is how System.nanoTime works on most, if not all platforms).
Instead of using a thread, just call your startTime and stopTime methods directly from your original thread.
Try this:
class ThreadGame {
JButton button;
MyAction my_action;
private final Timer timer = new Timer();
public static void main(String[] args) {
ThreadGame tg = new ThreadGame();
}
public ThreadGame() {
JFrame frame = new JFrame("Calculate time - Game");
button = new JButton("Start");
button.addActionListener(new MyAction());
frame.add(button);
frame.setSize(400, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
class MyAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
String text = (String) e.getActionCommand();
if (text.equals("Start")) {
timer.startTime();
button.setText("Stop");
} else {
timer.stopTime();
button.setText("Start");
}
}
}
class Timer {
public double startTime = 0.0;
public double stopTime = 0.0;
public boolean running = false;
public double elapsed = 0.0;
public void startTime() {
this.startTime = System.nanoTime();
this.running = true;
}
public void stopTime() {
this.stopTime = System.nanoTime();
this.running = false;
}
// Elasped time in seconds
public double getElapsedTime() {
return (this.startTime-this.stopTime)*1000000000.0;
}
}
}
If you want to learn how to use threads, try writing an application that solves a problem for which threads are a good fit. For example, write a small Swing application that lets you download a file from the web. As the file is downloading, update a progress bar in your UI. The download should happen in a worker thread separately from the UI thread, otherwise the UI will block during the download's progress.
Another example problem is to write a threaded ray tracer (here's an example tutorial written in C++).
If you want something simpler, write a Swing clock. Use a loop within a separate thread to update the UI at a periodic interval, but do not use the loop to manage what time it is. Again, don't try to keep time in the loop, just let the OS keep the time, and use the loop to schedule when the UI gets updated with the current OS time.
You're never calling getElapsedTime() that updates elapsed field.
You are creating a new Timer when ever you click the button. Make timer a class variable of your MyAction
The code below should be sufficient to get elapsed time.
class MyAction implements ActionListener {
final Timer timer = new Timer();
public void actionPerformed(ActionEvent e) {
String text = (String) e.getActionCommand();
if (text.equals("Start")) {
button.setText("Stop");
timer.startTime();
} else {
timer.stopTime();
System.out.println(timer.elapsed);
button.setText("Start");
}
}
}
Simply do this...
- Call System.currentTimeMillis() at the Starting of threads.
- Then again call System.currentTimeMillis() at the end of threads.
- Subtract the end with starting value to get the Elapsed time...
/////////////////EDITED///////////////////////
Make sure that the method trying to manipulate(ie. read and write) the variable holding the System.currentTimeMillis() must be synchronized, with synchronized keyword, so that Race Condition doesn't occur according to Brian's Law...
If you are writing a variable that might next be read by another thread, or reading a variable that might have last been written by another thread, you must use synchronization, and further, both the reader and the writer must synchronize using the same monitor lock.

Categories

Resources