如何在Java中以安全的方式停止和恢复线程?

时间:2012-03-16 05:02:27

标签: java multithreading

我正在编写一个继续发送请求的心跳对象, 但它可能暂停和恢复....但我可以阻止它,但不能恢复....

这是HeartBeat对象:

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();
}

heartBeatTask如下:

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();
        }
    }
}

这两个对象都是java中的一个runnable对象,我无法恢复跳动的错误:

我如何恢复殴打:

    this.beating();

我如何停止承受:

    this.stopBeating();

5 个答案:

答案 0 :(得分:2)

一种解决方案是使用wait()和notify()

答案 1 :(得分:1)

不幸的是,你不仅仅是一个殴打/非殴打状态。

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();
        }
    }
}

你需要能够暂停线程,在这种情况下我只是使用Object.wait()和Object.notify()。

其他选项可能包括使用线程池并在您希望再次启动作业时将此任务重新添加到池中。您只需要确保不要将任务添加两次,因为您必须经常跳动两次。

由于您正在编写每xxxx秒执行一次的内容,因此您可能需要查看ScheduledExecutorService。暂停/停止将涉及cancel任务,恢复将是重新添加任务的问题。

答案 2 :(得分:0)

另一个简单的解决方案是让线程停止并在恢复时创建一个新线程。如果您这样做,请使用线程池(可选,在小型独立应用程序中不需要)。

答案 3 :(得分:0)

您可以使用semaphore

以下是您的示例将如何发挥作用:

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();
        }
    }
}

答案 4 :(得分:0)

你的代码的问题是,在你的stop方法中,你将“isKeepHeartBeat”设置为false,然后你的线程完成了,但没有暂停。

所以你需要使用信号量或wait()让你的线程在那里等待,但是没有完成。