Java 并发编程实战学习笔记——路径查找类型并行任务的终止

1.该类问题的递归串行算法(深度优先遍历)

代码 复制 - 运行


package net.jcip.examples; 

import java.util.*; 

/** 
 * SequentialPuzzleSolver 
 * <p/> 
 * Sequential puzzle solver 
 * 
 * @author Brian Goetz and Tim Peierls 
 */ 

public class SequentialPuzzleSolver <P, M> { 
    private final Puzzle<P, M> puzzle; 
    private final Set<P> seen = new HashSet<P>(); 

    public SequentialPuzzleSolver(Puzzle<P, M> puzzle) { 
        this.puzzle = puzzle; 
    } 

    public List<M> solve() { 
        P pos = puzzle.initialPosition(); 
        return search(new PuzzleNode<P, M>(pos, null, null)); 
    } 

    private List<M> search(PuzzleNode<P, M> node) { 
        if (!seen.contains(node.pos)) { 
            seen.add(node.pos); 
            if (puzzle.isGoal(node.pos)) 
                return node.asMoveList(); 
            for (M move : puzzle.legalMoves(node.pos)) { 
                P pos = puzzle.move(node.pos, move); 
                PuzzleNode<P, M> child = new PuzzleNode<P, M>(pos, move, node); 
                List<M> result = search(child); 
                if (result != null) 
                    return result; 
            } 
        } 
        return null; 
    } 
} 


2.该类问题的并行算法(CountDownLatch 用作一个简单的开/关锁存器)
广度优先算法

代码 复制 - 运行


package net.jcip.examples; 

import java.util.concurrent.*; 

/** 
 * ValueLatch 
 * <p/> 
 * Result-bearing latch used by ConcurrentPuzzleSolver 
 * 
 * @author Brian Goetz and Tim Peierls 
 */ 
@ThreadSafe 
public class ValueLatch <T> { 
    @GuardedBy("this") private T value = null; 
    private final CountDownLatch done = new CountDownLatch(1); 

    public boolean isSet() { 
        return (done.getCount() == 0); 
    } 

    public synchronized void setValue(T newValue) { 
        if (!isSet()) { 
            value = newValue; 
            done.countDown(); 
        } 
    } 

    public T getValue() throws InterruptedException { 
        done.await(); 
        synchronized (this) { 
            return value; 
        } 
    } 
} 


代码 复制 - 运行


package net.jcip.examples; 

import java.util.*; 
import java.util.concurrent.*; 

/** 
 * ConcurrentPuzzleSolver 
 * <p/> 
 * Concurrent version of puzzle solver 
 * 
 * @author Brian Goetz and Tim Peierls 
 */ 
public class ConcurrentPuzzleSolver <P, M> { 
    private final Puzzle<P, M> puzzle; 
    private final ExecutorService exec; 
    private final ConcurrentMap<P, Boolean> seen; 
    protected final ValueLatch<PuzzleNode<P, M>> solution = new ValueLatch<PuzzleNode<P, M>>(); 

    public ConcurrentPuzzleSolver(Puzzle<P, M> puzzle) { 
        this.puzzle = puzzle; 
        this.exec = initThreadPool(); 
        this.seen = new ConcurrentHashMap<P, Boolean>(); 
        if (exec instanceof ThreadPoolExecutor) { 
            ThreadPoolExecutor tpe = (ThreadPoolExecutor) exec; 
            tpe.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); 
        } 
    } 

    private ExecutorService initThreadPool() { 
        return Executors.newCachedThreadPool(); 
    } 

    public List<M> solve() throws InterruptedException { 
        try { 
            P p = puzzle.initialPosition(); 
            exec.execute(newTask(p, null, null)); 
            // block until solution found 
            PuzzleNode<P, M> solnPuzzleNode = solution.getValue(); 
            return (solnPuzzleNode == null) ? null : solnPuzzleNode.asMoveList(); 
        } finally { 
            exec.shutdown(); 
        } 
    } 

    protected Runnable newTask(P p, M m, PuzzleNode<P, M> n) { 
        return new SolverTask(p, m, n); 
    } 

    protected class SolverTask extends PuzzleNode<P, M> implements Runnable { 
        SolverTask(P pos, M move, PuzzleNode<P, M> prev) { 
            super(pos, move, prev); 
        } 

        public void run() { 
            if (solution.isSet() 
                    || seen.putIfAbsent(pos, true) != null) 
                return; // already solved or seen this position 
            if (puzzle.isGoal(pos)) 
                solution.setValue(this); 
            else 
                for (M m : puzzle.legalMoves(pos)) 
                    exec.execute(newTask(puzzle.move(pos, m), m, this)); 
        } 
    } 
} 



该段代码有个问题,就是不能够感知到该问题没有答案。
因此可以改为,可以感知到任务不存在的解决中

代码 复制 - 运行


package net.jcip.examples; 

import java.util.concurrent.atomic.*; 

/** 
 * PuzzleSolver 
 * <p/> 
 * Solver that recognizes when no solution exists 
 * 
 * @author Brian Goetz and Tim Peierls 
 */ 
public class PuzzleSolver <P,M> extends ConcurrentPuzzleSolver<P, M> { 
    PuzzleSolver(Puzzle<P, M> puzzle) { 
        super(puzzle); 
    } 

    private final AtomicInteger taskCount = new AtomicInteger(0); 

    protected Runnable newTask(P p, M m, PuzzleNode<P, M> n) { 
        return new CountingSolverTask(p, m, n); 
    } 

    class CountingSolverTask extends SolverTask { 
        CountingSolverTask(P pos, M move, PuzzleNode<P, M> prev) { 
            super(pos, move, prev); 
            taskCount.incrementAndGet(); 
        } 

        public void run() { 
            try { 
                super.run(); 
            } finally { 
                if (taskCount.decrementAndGet() == 0) 
                    solution.setValue(null); 
            } 
        } 
    } 
} 

原文地址:https://www.cnblogs.com/daichangya/p/12959142.html