PlanExecutor implements JobResultReceiver, Cancelable, DependencyGraphExecutionFuture { public void start() { synchronized (this) { if (_state != State.NOT_STARTED) { s_logger.error("Already started executing {}", this); throw new IllegalStateException(_state.toString()); } _state = State.EXECUTING; _startTime = System.nanoTime(); } if (getGraph().isFinished()) { s_logger.info("Execution plan {} is empty", this); notifyComplete(); } else { s_logger.info("Starting executing {}", this); submitExecutableJobs(); } } PlanExecutor(final SingleComputationCycle cycle, final GraphExecutionPlan plan); void start(); @Override boolean cancel(final boolean mayInterruptIfRunning); @Override void resultReceived(final CalculationJobResult result); @Override synchronized boolean isCancelled(); @Override boolean isDone(); @Override synchronized String get(); @Override synchronized String get(final long timeout, final TimeUnit unit); @Override void setListener(final Listener listener); @Override String toString();  }
@Test(expectedExceptions = IllegalStateException.class) public void testDuplicateStart() { final PlanExecutor executor = new PlanExecutor(createCycle(new JobDispatcher()), createPlan()); executor.start(); executor.start(); }