2012-03-16 10 views
1

は私がリクエスト、 を送信し続けるハートビートオブジェクトを書いていますが、それは一時停止と再開....しかし、私はそれを止めることができますが、戻って再開することができないことがあり:Javaで安全にスレッドを停止して再開するにはどうすればよいですか?ここで <p></p>がハートビートオブジェクトです....

次のように
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で実行可能なオブジェクトです:

01私は、軸受を止める方法

this.beating(); 

::私は鼓動を再開方法

this.stopBeating(); 
+4

代わりに 'wait'と' notify'を試してみませんか? –

答えて

2

一つの解決策は、((待機を使用すること)と通知します)

0

別の簡単な解決策は、できるようにすることですスレッドは停止し、再開時に新しいスレッドを作成します。これを行う場合は、スレッドプールを使用します(小規模なスタンドアロンアプリでは必要ありません)。

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()を使用しています、スレッドを一時停止できるようにする必要があります。

その他のオプションには、スレッドプールを使用して、ジョブを再度開始するときにこのタスクをプールに再追加することなどがあります。あなたは、必要な回数の2倍の殴打回数を2回追加しないようにするだけです。

xxxx秒ごとに実行されるものを作成しているので、ScheduledExecutorServiceをチェックアウトするとよいでしょう。一時停止/停止にはタスクの再実行が含まれますが、再開するにはタスクを再追加する必要があります。

+0

Executorサービスを使用する2番目の提案は、より良い提案のようです。 – Tom

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

興味深い解決策ですが、呼び出される問題は、別のスレッドがbeating()を呼び出すまでstopBeating()呼び出しで呼び出しコードがブロックされることです。この場合、2つのスレッドが必要な場合、両方がstopBeating()を呼び出した場合、beating()を2回呼び出す必要があります。 – pimaster

+0

ええ、あなたはそれを守るための旗が必要です。 – Tom

0

問題は、あなたのstopメソッドでは、あなたのスレッドは終了し、その後、偽として「isKeepHeartBeat」を設定しますが、一時停止していない、ということです。

スレッドを待つが、終了しないようにするには、セマフォまたはwait()を使用する必要があります。

関連する問題