publicclassConcurrentPuzzleSolver<P,M>{privatefinalPuzzle<P,M>puzzle;privatefinalExecutorServiceexec;privatefinalConcurrentMap<P,Boolean>seen;protectedfinalValueLatch<PuzzleNode<P,M>>solution=newValueLatch<PuzzleNode<P,M>>();publicConcurrentPuzzleSolver(Puzzle<P,M>puzzle){this.puzzle=puzzle;this.exec=initThreadPool();this.seen=newConcurrentHashMap<P,Boolean>();if(execinstanceofThreadPoolExecutor){ThreadPoolExecutortpe=(ThreadPoolExecutor)exec;tpe.setRejectedExecutionHandler(newThreadPoolExecutor.DiscardPolicy());}}privateExecutorServiceinitThreadPool(){returnExecutors.newCachedThreadPool();}publicList<M>solve()throwsInterruptedException{try{Pp=puzzle.initialPosition();exec.execute(newTask(p,null,null));// block until solution foundPuzzleNode<P,M>solnPuzzleNode=solution.getValue();return(solnPuzzleNode==null)?null:solnPuzzleNode.asMoveList();}finally{exec.shutdown();}}protectedRunnablenewTask(Pp,Mm,PuzzleNode<P,M>n){returnnewSolverTask(p,m,n);}protectedclassSolverTaskextendsPuzzleNode<P,M>implementsRunnable{SolverTask(Ppos,Mmove,PuzzleNode<P,M>prev){super(pos,move,prev);}publicvoidrun(){if(solution.isSet()||seen.putIfAbsent(pos,true)!=null)return;// already solved or seen this positionif(puzzle.isGoal(pos))solution.setValue(this);elsefor(Mm:puzzle.legalMoves(pos))exec.execute(newTask(puzzle.move(pos,m),m,this));}}}@ThreadSafepublicclassValueLatch<T>{@GuardedBy("this")privateTvalue=null;privatefinalCountDownLatchdone=newCountDownLatch(1);publicbooleanisSet(){return(done.getCount()==0);}publicsynchronizedvoidsetValue(TnewValue){if(!isSet()){value=newValue;done.countDown();}}publicTgetValue()throwsInterruptedException{done.await();synchronized(this){returnvalue;}}}