@Override
  public void run() {

    logger.info("Thread " + threadHashKey + " is running...");

    while (stopFlag.intValue() == 0) {
      GameEvent event = null;
      try {
        event = queue.take();
        GameSession session = gameManager.findGameSessionById(event.getTargetSession());
        if (session == null) {
          GameLog.warn(
              event.getTargetSession(),
              "process event " + event.getKey() + " but session id not found ");
          continue;
        }

        boolean skipEvent = preHandleEvent(event, session);
        if (skipEvent) {
          continue;
        }

        com.orange.common.statemachine.State nextState =
            stateMachine.nextState(session.getCurrentState(), event, session);
        if (nextState == null) {
          GameLog.warn(
              event.getTargetSession(),
              "process event " + event.getKey() + " but next state not found");
          continue;
        }

        session.setCurrentState(nextState);

        /*
        GameSession session = gameManager.findGameSessionById(event.getTargetSession());
        if (session == null){
        	// no session available for this event?

        	GameLog.warn(event.getTargetSession(), "process event but session id not found ");
        	HandlerUtils.sendErrorResponse(event, GameResultCode.ERROR_NO_SESSION_ID);
        	continue;
        }

        if (session.getCurrentState().validateEvent(event, session) != 0){
        	// donnot send back request here since validate event will make it
        	// argument, where to send the response???
        	continue;
        }

         com.orange.common.statemachine.State nextState =
        	 stateMachine.nextState(session.getCurrentState(), event, session);

         if (nextState == null){
        	 // incorrect message event?
        	 HandlerUtils.sendErrorResponse(event, GameResultCode.ERROR_NEXT_STATE_NOT_FOUND);
        	 continue;
         }

         session.setCurrentState(nextState);
         */

      } catch (Exception e) {
        logger.error("catch exception while handle event, exception = " + e.toString(), e);
        // rem by Benson for refactor
        //				if (event != null){
        //					HandlerUtils.sendErrorResponse(event, GameResultCode.ERROR_SYSTEM_EXCEPTION);
        //				}
      }
    }

    logger.info("Thread " + threadHashKey + " is stop...");
  }
public class GameWorkerThread extends Thread {

  protected static final Logger logger = Logger.getLogger(GameWorkerThread.class.getName());

  //	static final StateMachine stateMachine =
  // GameStateMachineBuilder.getInstance().buildStateMachine();
  static final StateMachine stateMachine =
      NewGameStateMachineBuilder.getInstance().buildStateMachine();
  GameSessionManager gameManager = GameSessionManager.getInstance();
  GameService gameService = GameService.getInstance();
  PriorityBlockingQueue<GameEvent> queue = new PriorityBlockingQueue<GameEvent>(4096);
  AtomicInteger stopFlag = new AtomicInteger(0);

  public int threadHashKey;

  @Override
  public void run() {

    logger.info("Thread " + threadHashKey + " is running...");

    while (stopFlag.intValue() == 0) {
      GameEvent event = null;
      try {
        event = queue.take();
        GameSession session = gameManager.findGameSessionById(event.getTargetSession());
        if (session == null) {
          GameLog.warn(
              event.getTargetSession(),
              "process event " + event.getKey() + " but session id not found ");
          continue;
        }

        boolean skipEvent = preHandleEvent(event, session);
        if (skipEvent) {
          continue;
        }

        com.orange.common.statemachine.State nextState =
            stateMachine.nextState(session.getCurrentState(), event, session);
        if (nextState == null) {
          GameLog.warn(
              event.getTargetSession(),
              "process event " + event.getKey() + " but next state not found");
          continue;
        }

        session.setCurrentState(nextState);

        /*
        GameSession session = gameManager.findGameSessionById(event.getTargetSession());
        if (session == null){
        	// no session available for this event?

        	GameLog.warn(event.getTargetSession(), "process event but session id not found ");
        	HandlerUtils.sendErrorResponse(event, GameResultCode.ERROR_NO_SESSION_ID);
        	continue;
        }

        if (session.getCurrentState().validateEvent(event, session) != 0){
        	// donnot send back request here since validate event will make it
        	// argument, where to send the response???
        	continue;
        }

         com.orange.common.statemachine.State nextState =
        	 stateMachine.nextState(session.getCurrentState(), event, session);

         if (nextState == null){
        	 // incorrect message event?
        	 HandlerUtils.sendErrorResponse(event, GameResultCode.ERROR_NEXT_STATE_NOT_FOUND);
        	 continue;
         }

         session.setCurrentState(nextState);
         */

      } catch (Exception e) {
        logger.error("catch exception while handle event, exception = " + e.toString(), e);
        // rem by Benson for refactor
        //				if (event != null){
        //					HandlerUtils.sendErrorResponse(event, GameResultCode.ERROR_SYSTEM_EXCEPTION);
        //				}
      }
    }

    logger.info("Thread " + threadHashKey + " is stop...");
  }

  private boolean preHandleEvent(GameEvent event, GameSession session) {
    AbstractRequestHandler handler = null;
    switch ((GameCommandType) event.getKey()) {
      case START_GAME_REQUEST:
        handler = new StartGameRequestHandler(event, session);
        break;
      case CLEAN_DRAW_REQUEST:
        handler = new CleanDrawRequestHandler(event, session);
        break;
      case SEND_DRAW_DATA_REQUEST:
        handler = new DrawDataRequestHandler(event, session);
        break;
      case CHAT_REQUEST:
        handler = new ChatRequestHandler(event, session);
        break;
      default:
        return false;
    }

    if (handler == null) return false;

    try {
      handler.handleRequest(event.getMessage());
    } catch (Exception e) {
      GameLog.error(event.getTargetSession(), e);
    }
    return true;
  }

  public void stopGraceful() {
    logger.info("Thread " + threadHashKey + " try stop gracefully");
    stopFlag.incrementAndGet();
  }

  public void putEvent(GameEvent gameEvent) {
    try {
      queue.put(gameEvent);
    } catch (Exception e) {
      logger.error("<putEvent> but catch exception " + e.toString(), e);
    }
  }

  //	public void putEventHead(GameEvent gameEvent) {
  //		try {
  //			queue.put(gameEvent);
  //		} catch (Exception e) {
  //			logger.error("<putEventHead> but catch exception " + e.toString(), e);
  //		}
  //	}

}