Reputation: 51
Right now I have a method that (correctly) updates a label on a GUI to count down from user input from a form text box:
private void bendStopCounter() throws AWTException {
Thread counter = new Thread() {
public void run() {
// timeAway is the user input int in miliseconds, hence the conversion
for (int i=(int)(timeAway/1000); i>0; i=i-1) {
updateGUI(i,lblBendingStopTimer);
try {Thread.sleep(1000);} catch(InterruptedException e) {};
}
}
public void updateGUI(final int i, final Label lblBendingTimer) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
lblBendingTimer.setText("Time until bending stops: " + i/60 + " minutes and " + i%60 + " seconds.");
}
});
}
};
counter.start();
}
This is the listener button logic on my GUI. It parses date/time from the form and (correctly) executes logic from the BendingController class to do something:
private void addBendingListener()
{
executeBendingButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
System.out.println("Bending has started! lolool");
//grabs UI values and pass them to controller
int day = dateTimeDMY.getDay();
int month = dateTimeDMY.getMonth();
int year = dateTimeDMY.getYear();
int hour = dateTimeHMS.getHours();
int minute = dateTimeHMS.getMinutes();
int second = dateTimeHMS.getSeconds();
Date date = parseDate(day, month, year, hour, minute, second);
try {
System.out.println("Waiting for " + date + " to happen...");
timeAway = Long.parseLong(timeAwayInMinutes.getText());
timeAway = TimeUnit.MINUTES.toMillis(timeAway);
timer.schedule(new BenderController(timeAway,cursorMoveIncrement), date);
timeAway = TimeUnit.MILLISECONDS.toMillis(timeAway);
bendStopCounter();
}
catch (Exception exc) {
MessageDialog.openError(shell, "Error", "Hey, jerkwad, you see those 2 friggin' textboxs? Yeah, put valid numbers in them next time, asshole!");
return;
}
}
});
}
My bug is if the user chooses a start date/time anytime in the future, the counter starts counting down as soon as the execute button is pressed. The BenderController class logic will execute at a specific time, because it is extending TimerTask and is using the schedule() method as seen above. I want the bendStopCounter() method to use something similar to this and start executing at the same time as the chosen date/time.
Thoughts?
Upvotes: 0
Views: 87
Reputation: 141
For short term stuff like minutes or even hours that have no problem with getting lost on a restart of the program (unexpected poweroff for example) you can just use the java executors.(SheduledExecutor)
As you seem to have a requirement to be able to schedule days/months/years ahead go with quartz as mentioned by Williams answer. It has an inbuilt job storage possibility to persist setup jobs.
However some sample code for Executors:
public class ExecTest
{
public static void main(String[] args)
{
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); //create an executor with 1 worker thread.
final ScheduledFuture future =
executor.scheduleAtFixedRate(new TimeCounter(System.out), 0, 1000, TimeUnit.MILLISECONDS); //execute Timecounter every 1k milliseconds
executor.schedule(
new Runnable()
{
ScheduledFuture fut= future; //grabbing the final future
public void run() {
fut.cancel(false); //cancel the endless counter using its future
}
}
, 6000, TimeUnit.MILLISECONDS); //shedule it once in 6 seks
}
}
public class TimeCounter implements Runnable
{
private PrintStream display;
private long startTime;
public TimeCounter(PrintStream out)
{
startTime=System.currentTimeMillis();
display= out;
}
public void run()
{
updateGUI((System.currentTimeMillis()-startTime)/1000);
}
private void updateGUI(final long i)
{
display.println("Time until bending stops: " + i/60 + " minutes and " + i%60 + " seconds.");
}
}
Upvotes: 1
Reputation: 820
You would use a library like Quartz to do this. It is very easy to use and you can use Cron syntax which is very easy to find information on so you can make your specific schedules.
Upvotes: 1