Reputation: 30568
I am writing a heartbeat object that will keep sending request, but it may pause and resume....But I can stop it, but can't resume back....
Here is the HeartBeat Object:
public void startBeating() {
heartBeatTask = new HeartBeatTask(monitorInterval);
heartBeatTaskThread = new Thread(heartBeatTask);
}
public void stopBeating() {
heartBeatTask.setKeepHeartBeat(false);
}
public void beating() {
heartBeatTask.setKeepHeartBeat(true);
}
@Override
public void run() {
this.startBeating();
this.beating();
heartBeatTaskThread.start();
}
And the heartBeatTask as follow:
public HeartBeatTask(long aHeartBeatInterval){
this.heartBeatInterval = aHeartBeatInterval;
}
@Override
public void run() {
while(isKeepHeartBeat()){
System.out.println("beating");
try {
Thread.sleep(this.heartBeatInterval);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Both object is a runnable object in java, what's going wrong that I can't resume the beating:
How I resume the beating:
this.beating();
How I stop bearing:
this.stopBeating();
Upvotes: 1
Views: 487
Reputation: 3883
The problem of your code is that, in your stop method, you set "isKeepHeartBeat" as false, then your thread finished, but not paused.
So you need to use semaphore or wait() to let your thread to wait there, but not finished.
Upvotes: 0
Reputation: 44821
You could use a semaphore.
Here's how your example would play out:
public void startBeating() {
semaphore = new Semaphore(1);
heartBeatTask = new HeartBeatTask(monitorInterval, semaphore);
heartBeatTaskThread = new Thread(heartBeatTask);
}
public void stopBeating() {
try {
semaphore.aquire();
} catch (InterruptedException e) {
}
}
public void beating() {
semaphore.release();
}
@Override
public void run() {
this.startBeating();
this.beating();
heartBeatTaskThread.start();
}
public HeartBeatTask(long aHeartBeatInterval, Semaphore semaphore){
this.heartBeatInterval = aHeartBeatInterval;
this.semaphore = semaphore;
}
@Override
public void run() {
while(isKeepHeartBeat()){
System.out.println("beating");
try {
Thread.sleep(this.heartBeatInterval);
semaphore.acquire(); // we acquire then immediately release
semaphore.release(); // so that if the other thread has
// already acquired it we'll block (so not beat).
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Upvotes: 0
Reputation: 1967
Unfortuntely, you have more than just a beating/non beating state.
public class test
{
public static void main(String[] args) throws Exception
{
HeartBeat hb = new HeartBeat();
Thread t = new Thread(hb);
t.start();
Thread.sleep(1500);
hb.setPaused(true);
Thread.sleep(1500);
hb.setPaused(false);
Thread.sleep(1500);
hb.stopBeating();
t.join(); // make sure the thread terminates correctly;
System.out.println("Patient is dead.");
}
}
class HeartBeat implements Runnable
{
private final Object lock = new Object();
private volatile boolean paused = false;
private volatile boolean running = true;
public void run()
{
while (running)
{
if(paused)
{
synchronized (lock)
{
try
{
while (paused)
{
lock.wait();
}
}
catch (InterruptedException e)
{
}
}
}
else
{
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
}
System.out.println("Beat");
}
}
}
public void stopBeating()
{
synchronized (lock)
{
running = false;
paused = false;
lock.notifyAll();
}
}
public void setPaused(boolean paused)
{
synchronized (lock)
{
this.paused = paused;
lock.notifyAll();
}
}
}
You need to be able to pause the thread, in this case I am just using the Object.wait() and Object.notify().
Other options could include using a Thread pool and re-adding this task to the pool when you want to start the job again. You just need to make sure that you don't add the task twice as you'd be beating twice as often as necessary.
Since you are writing something that gets executed every xxxx seconds, you might want to check out the ScheduledExecutorService
. Pausing/stopping would involve cancel
ing the task, resuming would be a matter of re-adding the task.
Upvotes: 1
Reputation: 7706
Another simple solution is to let the thread die on stop and create a new thread on resume. Use a thread pool if you do this (optional and not necessary in a small standalone app).
Upvotes: 0