Java-这个信号缺失解决方案可以吗?

Java-这个信号缺失解决方案可以吗?,java,concurrency,signals,wait,notify,Java,Concurrency,Signals,Wait,Notify,我已经创造了一个游戏,我希望一个球员坐了一段时间后被删除。runnable PlayerRemover类包含runnable GameTimer类的实例。PlayerRemover创建一个GameTimer线程,该线程会停止计时或手动停止,然后通知PlayerRemover线程continue 我担心如果在wait()之前调用notify()可能会丢失信号,因此我决定让GameTimer线程通知,直到PlayerRemover线程将GameTimer中的布尔变量设置为false 我在网上寻找了一

我已经创造了一个游戏,我希望一个球员坐了一段时间后被删除。runnable PlayerRemover类包含runnable GameTimer类的实例。PlayerRemover创建一个GameTimer线程,该线程会停止计时或手动停止,然后通知PlayerRemover线程continue

我担心如果在wait()之前调用notify()可能会丢失信号,因此我决定让GameTimer线程通知,直到PlayerRemover线程将GameTimer中的布尔变量设置为false

我在网上寻找了一些解决丢失信号的方法,但没有提到这一点,使用带有原子代码块的while循环让我想知道这是否有一个很好的理由

我的代码运行良好,但这种方法会出现问题吗?有没有更好更标准的方法

谢谢你的帮助,谢谢

public class PlayerRemover implements Runnable
{
  private final GameTimer timer;
  private final int seat;
  private final BlackjackPlayer p;
  private boolean wasSignalled;

  public PlayerRemover(TableFrame gui, GameTimer t)
  {
    timer = t;
    seat = gui.getTablePanel().getSeatIndex() ;
    p = gui.getTablePanel().getBlackjackPlayer();
    wasSignalled = false;
  }        

  @Override
  public void run()
  {
     Thread timerThread = new Thread(timer);
     timerThread.start();

     synchronized(timerThread)
     {    
       while (g[seat] != null && p.getState() == State.SITTING_OUT &&          timer.getSecondsLeft() > 0)
       {
           try {
               timerThread.wait();
           } catch (InterruptedException ex) {
               Logger.getLogger(TableCoord.class.getName()).log(Level.SEVERE, null, ex);
           }
       }
     }  

     timer.setSignalRecieved();
     timer.stopTimer();

     if (g[seat] != null && timer.getSecondsLeft() == 0)
     {
       removePlayer(p,seat);
       updateAllGUIs();
     }    
  }        
}



public class GameTimer implements Runnable {

private int secondsLeft; 
private boolean timerStop; 
private boolean doNotify;
private boolean signalReceived;

/**
* Creates a timer with a given number of seconds on the clock.
*/
public GameTimer(int seconds,boolean notifyThis)
{      
  secondsLeft = seconds;
  timerStop = false; 
  doNotify = notifyThis;
  signalReceived = false;
}

public GameTimer(int seconds)
{     
  secondsLeft = seconds;
  timerStop = false; 
  doNotify = false;
}

/**
* Stops timer permanently 
*/
public void stopTimer()
{
  timerStop = true;
}

public int getSecondsLeft()
{
   return secondsLeft;   
}         

public boolean getTimerStop()
{
  return timerStop;
 }         

public void setSignalRecieved()
{
 signalReceived = true;
}



 @Override
 public void run()
 {
   // While there timer is still counting down or all players finish 
   // their actions.
    while (!timerStop)
    {    
      // Wait 1 second  
      try
      {
       Thread.sleep(1000);
      }
      catch (Exception e)
      {
        System.out.println("Error: " + e.toString());
      }  

      //decrement timer 1 second
       secondsLeft--;

      if (secondsLeft <= 0)
      {
       timerStop = true;
      } 
    } 

    timerStop= true;
    if (doNotify)
    {  
     while (!signalReceived) 
    {    
       synchronized(this)
       {
         notify();
         try
         {
           Thread.sleep(100);
         }
         catch (Exception e)
         {
           System.out.println("Error: " + e.getMessage());
         }    
       }
     } 
   }
  }
 }
公共类PlayerRemover实现可运行
{
私人最终游戏计时器;
非公开最终席位;
私人决赛黑杰克;
专用布尔信号;
公共PlayerRemover(TableFrame gui,GameTimer)
{
定时器=t;
seat=gui.getTablePanel().getSeatIndex();
p=gui.getTablePanel().getBlackjackPlayer();
WASSignaled=错误;
}        
@凌驾
公开募捐
{
线程计时器读取=新线程(计时器);
timerThread.start();
已同步(timerThread)
{    
while(g[seat]!=null&&p.getState()==State.siting_OUT&&timer.getSecondsLeft()>0)
{
试一试{
timerThread.wait();
}捕获(中断异常例外){
Logger.getLogger(TableCoord.class.getName()).log(Level.SEVERE,null,ex);
}
}
}  
timer.setSignalReceived();
timer.stopTimer();
如果(g[seat]!=null&&timer.getSecondsLeft()=0)
{
移除播放器(p,座椅);
updatealguis();
}    
}        
}
公共类GameTimer实现可运行{
私家车;
私有布尔定时器;
私有布尔doNotify;
接收到私有布尔信号;
/**
*创建时钟上具有给定秒数的计时器。
*/
公共游戏计时器(整数秒,布尔值)
{      
secondsLeft=秒;
timerStop=false;
doNotify=通知此项;
信号接收=假;
}
公共游戏计时器(整数秒)
{     
secondsLeft=秒;
timerStop=false;
doNotify=false;
}
/**
*永久停止计时器
*/
公共无效停止计时器()
{
timerStop=true;
}
public int getSecondsLeft()
{
返回第二个sleft;
}         
公共布尔getTimerStop()
{
返回计时器;
}         
公共无效设置已接收信号()
{
信号接收=真;
}
@凌驾
公开募捐
{
//当计时器仍在倒数或所有玩家完成时
//他们的行动。
而(!timerStop)
{    
//等一秒钟
尝试
{
睡眠(1000);
}
捕获(例外e)
{
System.out.println(“错误:+e.toString());
}  
//减量计时器1秒
第二步--;

if(secondsLeft对于大多数任务,wait()和notify()方法通常太低级且容易出错

JavaDoc中的一个示例演示了固定速率可重复任务和一次性任务:

下面是一个类,该类具有一个方法,该方法将ScheduledExecutorService设置为每10秒发出一次嘟嘟声,持续一小时:

导入静态java.util.concurrent.TimeUnit.*;
类蜂鸣器控制{
专用最终计划执行器服务计划程序=
Executors.newScheduledThreadPool(1);
公共空间{
最终可运行蜂鸣器=新可运行(){
public void run(){System.out.println(“beep”);}
};
最终计划的未来蜂鸣器手柄=
scheduleAtFixedRate(蜂鸣器,10秒,10秒);
scheduler.schedule(新的Runnable(){
public void run(){beeperHandle.cancel(true);}
},60*60,秒);
}
}
import static java.util.concurrent.TimeUnit.*;


class BeeperControl {
   private final ScheduledExecutorService scheduler =
     Executors.newScheduledThreadPool(1);

   public void beepForAnHour() {
     final Runnable beeper = new Runnable() {
       public void run() { System.out.println("beep"); }
     };
     final ScheduledFuture<?> beeperHandle =
       scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
     scheduler.schedule(new Runnable() {
       public void run() { beeperHandle.cancel(true); }
     }, 60 * 60, SECONDS);
   }
 }