void (final MyAction action) { LOG.debug("doAction: START " + action.name()); final MyExitAction[] exitActions; List<Runnable> toBeCalled = null; synchronized (myLock) { final MyState oldState = myState; myState = myState.transition(action); if (oldState.equals(myState)) return; exitActions = MyTransitionAction.getExit(oldState, myState); LOG.debug("doAction: oldState: " + oldState.name() + ", newState: " + myState.name()); if (LOG.isDebugEnabled() && exitActions != null) { final String debugExitActions = StringUtil.join(exitActions, exitAction -> exitAction.name(), " "); LOG.debug("exit actions: " + debugExitActions); } if (exitActions != null) { for (MyExitAction exitAction : exitActions) { if (MyExitAction.markStart.equals(exitAction)) { myWaitingFinishListeners.addAll(myWaitingStartListeners); myWaitingStartListeners.clear(); } else if (MyExitAction.markEnd.equals(exitAction)) { toBeCalled = new ArrayList<>(myWaitingFinishListeners); myWaitingFinishListeners.clear(); } } } } if (exitActions != null) { for (MyExitAction exitAction : exitActions) { if (MyExitAction.submitRequestToExecutor.equals(exitAction)) { myExecutor.consume((Runnable)() -> run()); } } } if (toBeCalled != null) { for (Runnable runnable : toBeCalled) { runnable.run(); } } LOG.debug("doAction: END " + action.name()); }