My situation is, I have two concurrent threads, one that cant start a timer and the other can stop the timer. The timer works in a way such that, once it has started it will count to 5 seconds and execute a function after, it will keep doing this until the timer is stopped by the other thread. How can this be implemented in Java. This is what I have, I feel it is the wrong way of doing it:
Note that sleep is a global volatile variable that the other two threads turn on and off.
void creatTime(final EventHandler handler)
{
Thread timer = new Thread()
{
public void run()
{
try
{
while(true)
{
while(sleep) Thread.sleep(1000);
//invoke function
}
}
catch(IOException e)
{
System.out.println(e);
}
}
};
timer.start();
}
}
You can create a TimerTask and schedule it to run every 5 seconds
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
// TODO Auto-generated method stub
//Invoke your function here
}
};
//Create a Timer and schedule it
Timer timer = new Timer();
timer.scheduleAtFixedRate(timerTask, 0, 5*1000);
//To terminate the Timer you can call its cancel method.
I agree with the TimerTask recommendation. In general, the more of your thread-related work you can pass on to the higher level features of java.util.concurrent etc. the better. For example, the original code does not deal with early wake-ups from sleep.
In addition, if the sleep variable remains after redesign, it needs to be marked volatile or accessed through synchronized get and set methods. There is a limited set of activities that ensure that writes done in one thread must become visible to reads done in another thread.
Related
The version of Java is 8u60.
I want to write a void method which could pause the program for 1 seconds but there are always exceptions.
public void OnePause(){
Timer timerOne = new Timer();
timerOne.schedule(timerOneTask(), (long)1000);}
private TimerTask timerOneTask() {
return null;
}
}
I do not want to use Thread.Sleep(); because it pauses the sum of all time when called multiple times instead of pause separately.
Thanks a lot.
Right now your code is broken. Besides trying to send null into Timer.schedule(...), your statement timerOne.schedule(timerOneTask(), (long)1000);} is going to call timerOneTask() every 1000 milliseconds, but that does not pause the program. You must sleep the thread:
private TimerTask timerOneTask(int sleepTime) {
return new DoNothingTimerTask extends TimerTask {
public void run() {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
// awoken prematurely, handle this
}
}
}
Unless you need to schedule the "pauses" on some interval, there's no use in introducing the Timer API into the mix; if not, you can get simply use what's in that try...finally block.
I'm having a bit of an annoying problem. Right now, I have a snippet of code that starts a thread, sets a timer within that thread, and then exits that thread and continues with its life. My intent here was for the program to wait for the TimerTask to complete before continuing with code flow. However, obviously, setting up a new TimerTask doesn't pause execution to wait for the timer to run down.
How do I set this up so that my code reaches the TimerTask, waits for the TimerTask to expire, and then continues? Should I even be using a Timer at all? I've looked everywhere for a solution, but I Can't seem to find one.
timer = new Timer();
Thread t = new Thread(new Runnable(){
boolean isRunning = true;
public void run() {
int delay = 1000;
int period = 1000;
interval = 10;
timerPanel.setText(interval.toString());
//Scheduling the below TimerTask doesn't wait
//for the TimerTask to finish before continuing
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
timerPanel.setText(setInterval().toString());
}
}, delay, period);
System.out.println("Thread done.");
}
});
t.start();
try {
t.join(); //doesn't work as I wanted
} catch (InterruptedException e) {
e.printStackTrace();
}
endTask();
Thanks in advance.
EDIT: Sorry for the confusion about the repeated task. I need the task to repeat because it's a countdown timer that pulses every second from 10 to 0. The function setInterval() eventually cancels the timer. Here's the relevant code:
private final Integer setInterval() {
if (interval == 1)
timer.cancel();
return --interval;
}
I believe a CountDownLatch will do what you want.
final CountDownLatch latch = new CountDownLatch(10);
int delay = 1000;
int period = 1000;
timerPanel.setText(Long.toString(latch.getCount()));
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
latch.countDown();
timerPanel.setText(Long.toString(latch.getCount()));
}
}, delay, period);
try {
latch.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
timer.cancel();
You should use Thread.sleep function instead of TimeTask to halt execution.
TimerTask is not meant to halt execution, its like a clock running in background. So for your requirement you should go for Thread.sleep.
Use a Semaphore. Initialize it before declaring the timer task, with 0 permits. In the timer task, use a try/finally block to release the semaphore. In the main thread, acquire the permit from the semaphore.
In your code, join works as specified since it waits for the thread to finish. And no, using a thread for this is not necessary. If you really want to block until a certain time, you don't need a Timer. Get the current time, compute the millis until the future time, and sleep().
I'm using Timer() due to its accuracy but works in the same was as PostDelayed Handler. It's called only once. Here is the Timer code:
public void setWFT() {
WFT = new Timer();
WFT.schedule(new TimerTask() {
#Override
public void run() {
WFTTimerMethod();
}
}, 60000); // 60 seconds delay
}
private void WFTTimerMethod() {
this.runOnUiThread(Timer_Tick);
}
private Runnable Timer_Tick = new Runnable() {
public void run() {
// My commands here
}
};
This only calls run() once after 60 seconds once the Timer is started. Sometimes, I have to cancel the Timer to Update the delay (replace the "60000" value). To start the Timer again, I simply recreate the Timer by calling WFT() again with the new delay value.
Problem is, when I cancel the timer using:
WFT.cancel();
WFT.purge();
The Timer does not start. the run() doesn't execute when it's supposed to. So my question is do I use cancel() and purge() or just cancel()?
Thanks
From the Java API on purge():
Most programs will have no need to call this method. It is designed for use by the rare application that cancels a large number of tasks. Calling this method trades time for space: the runtime of the method may be proportional to n + c log n, where n is the number of tasks in the queue and c is the number of cancelled tasks.
So you only need to call cancel()
from cancel() documentation :
No more tasks may be scheduled on this Timer.
I have a main form with a button, that when pressed, should start a new count-down timer thread.
This is the code in the button's action listener:
Counter c = new Counter(timeToFinish);
This is the code for the Counter class:
class Counter implements Runnable {
int waitingTime = 0;
Thread myCounter = new Thread(this);
public Counter(int waitingTime)
{
this.waitingTime = waitingTime;
myCounter.run();
}
public void run(){
//Start countdown:
do
{
waitingTime -= 1;
try {
Thread.sleep(1000);
System.out.println(waitingTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (waitingTime >= 0);
}
}
The problem is, when I create a new instance of the Counter class, it pauses the whole program, not just that thread! The problem must be with "Thread.sleep".
Because you are directly calling the run method.
Instead you should wrap it in a Thread and start the thread.
For e.g., replace
myCounter.run();
by
new Thread(this).start();
Just because you call the run method from the Counter constructor. That's not how it works with threads. You'll have to remove this call, wrap the Runnable in a Thread instance and call start() on the thread:
new Thread(new Counter(2)).start();
You aren't actually start()ing multiple threads.
The Thread.run() method simply runs the code associated with the thread, like any other normal function. It doesn't start a separate thread.
You need to call Thread.start(), to start a new thread and run your code in it.
You should use start() method of your thread. Use
c.start();
otherwise you have a class and you are invoking one of its methods, and of course it is running in main thread and sleeping the main thread.
You're calling run directly, it'll run in the current thread, and sleep the current thread, which I guess is the event thread. This cause the pause in your program.
You should use SwingUtilities class
see
http://www.java2s.com/Code/Java/Threads/InvokeExampleSwingandthread.htm
// Report the result using invokeLater().
SwingUtilities.invokeLater(new Runnable() {
public void run() {
resultLabel.setText("Ready");
setEnabled(true);
}
});
}
};
I want a thread to execute in the background every 500 milliseconds. To do that, I extended a Thread, implemented ActionListener and put the class that I extended into a Timer. The Timer calls run() every 500 milliseconds. However, my whole Swing GUI freezes up when this thread is downloading stuff from the Internet. I want it to run in the background, without freezing up the GUI while it waits for IO to finish. I also the downloader to finish downloading before we wait 500 milliseconds.
gogogo() is called to initialize the whole process:
public final class Downloader extends Thread implements ActionListener
{
public static void gogogo()
{
t= new Downloader();
new Timer(500, (ActionListener) t).start();
}
public void run()
{
doStuff(); //the code that i want repeatedly called
}
public void actionPerformed(ActionEvent e)
{
run();
}
}
Just start the thread once, make it loop, and do Thread.sleep(500L) with each iteration. That probably makes more sense that starting a brand new thread every 500ms. No reason to incur the associated cost if you can avoid it.
Instead of using the swing timer try using the java util timer or the ScheduledExecutorService. the swing timers share a pre-existing timer thread and that may be causing the freezing.
A recommendation from the java tutorial:
In general, we recommend using Swing timers rather than general-purpose timers for GUI-related tasks because Swing timers all share the same, pre-existing timer thread and the GUI-related task automatically executes on the event-dispatch thread. However, you might use a general-purpose timer if you don't plan on touching the GUI from the timer, or need to perform lengthy processing
If your GUI is freezing up, then your lengthly task (doStuff) is probably running on the Event Dispatching Thread. While it hogs that thread, other actions can't use it.
If you're trying to run a task repeatedly, you may be better off with the TimerTask class
public class Downloader extends TimerTask {
public void run() {
doStuff();
}
}
... elsewhere ...
Timer myTimer = new Timer();
public void gogogo() {
myTimer.scheduleAtFixedRate(new Downloader(), 0, 500);
}
That's a little different in that your task will be scheduled to run every 500 ms rather than with a 500 ms delay. When you're done, just use myTimer.cancel() to stop the repeating task execution.
You need to start the thread on each timer action. Calling the thread's run() method does not start the thread.
public void actionPerformed(ActionEvent e)
{
//run();
Downloader t = new Downloader();
t.start();
}
Might be better to use an anonymous class for the actionlistener. Excuse my java syntax but I have not verified it...
new Timer(500,
new ActionListener(){
public void actionPerformed(ActionEvent e)
{
//run();
Downloader t = new Downloader();
t.start();
}
}).start();
Or without the timer...
public static void gogogo()
{
t= new Downloader();
t.start();
}
public void run()
{
while(true){
doStuff(); //the code that i want repeatedly called
Thread.sleep(500);
}
}
Hmm, most likely all you need to do is reduce the thread priority, so it doesn't eat all your resources.