Java Reference
In-Depth Information
Node in Listing 8.14 represents a position that has been reached through some series of
moves, holding a reference to the move that created the position and the previous Node . Fol-
lowing the links back from a Node lets us reconstruct the sequence of moves that led to the
current position.
SequentialPuzzleSolver in Listing 8.15 shows a sequential solver for the puzzle
framework that performs a depth-first search of the puzzle space. It terminates when it finds
a solution (which is not necessarily the shortest solution).
Rewriting the solver to exploit concurrency would allow us to compute next moves and eval-
uate the goal condition in parallel, since the process of evaluating one move is mostly in-
dependent of evaluating other moves. (We say “mostly” because tasks share some mutable
state, such as the set of seen positions.) If multiple processors are available, this could reduce
the time it takes to find a solution.
ConcurrentPuzzleSolver in Listing 8.16 uses an inner SolverTask class that ex-
tends Node and implements Runnable . Most of the work is done in run : evaluating the
set of possible next positions, pruning positions already searched, evaluating whether success
has yet been achieved (by this task or by some other task), and submitting unsearched posi-
tions to an Executor .
To avoid infinite loops, the sequential version maintained a Set of previously searched po-
sitions; ConcurrentPuzzleSolver uses a ConcurrentHashMap for this purpose.
This provides thread safety and avoids the race condition inherent in conditionally updating a
shared collection by using putIfAbsent to atomically add a position only if it was not pre-
viously known. ConcurrentPuzzleSolver uses the internal work queue of the thread
pool instead of the call stack to hold the state of the search.
Search WWH ::




Custom Search