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);
}
}
}
}
Java 并发编程实战学习笔记——路径查找类型并行任务的终止的更多相关文章
- java并发编程实战学习(3)--基础构建模块
转自:java并发编程实战 5.3阻塞队列和生产者-消费者模式 BlockingQueue阻塞队列提供可阻塞的put和take方法,以及支持定时的offer和poll方法.如果队列已经满了,那么put ...
- 《java并发编程实战》笔记
<java并发编程实战>这本书配合并发编程网中的并发系列文章一起看,效果会好很多. 并发系列的文章链接为: Java并发性和多线程介绍目录 建议: <java并发编程实战>第 ...
- Java并发编程实战 读书笔记(一)
最近在看多线程经典书籍Java并发变成实战,很多概念有疑惑,虽然工作中很少用到多线程,但觉得还是自己太弱了.加油.记一些随笔.下面简单介绍一下线程. 一 线程与进程 进程与线程的解释 个人觉 ...
- Java并发编程实战 读书笔记(二)
关于发布和逸出 并发编程实践中,this引用逃逸("this"escape)是指对象还没有构造完成,它的this引用就被发布出去了.这是危及到线程安全的,因为其他线程有可能通过这个 ...
- 《Java并发编程实战》笔记-非阻塞算法
如果在某种算法中,一个线程的失败或挂起不会导致其他线程也失败和挂起,那么这种算法就被称为非阻塞算法.如果在算法的每个步骤中都存在某个线程能够执行下去,那么这种算法也被称为无锁(Lock-Free)算法 ...
- 《Java并发编程的艺术》第4章 Java并发编程基础 ——学习笔记
参考https://www.cnblogs.com/lilinzhiyu/p/8086235.html 4.1 线程简介 进程:操作系统在运行一个程序时,会为其创建一个进程. 线程:是进程的一个执行单 ...
- 《Java并发编程实战》笔记-Happens-Before规则
Happens-Before规则 程序顺序规则.如果程序中操作A在操作B之前,那么在线程中A操作将在B操作之前执行. 监视器锁规则.在监视器锁上的解锁操作必须在同一个监视器锁上的加锁操作之前执行. v ...
- 《Java并发编程实战》笔记-锁与原子变量性能比较
如果线程本地的计算量较少,那么在锁和原子变量上的竞争将非常激烈.如果线程本地的计算量较多,那么在锁和原子变量上的竞争会降低,因为在线程中访问锁和原子变量的频率将降低. 在高度竞争的情况下,锁的性能将超 ...
- 《Java并发编程实战》笔记-OneValueCache与原子引用技术
/** * NumberRange * <p/> * Number range class that does not sufficiently protect its invariant ...
- 《Java并发编程实战》笔记-状态依赖方法的标准形式
void stateDependentMethod() throws InterruptedException { //必须通过一个锁来保护条件谓词 synchronized(lock) { whil ...
随机推荐
- 调用ArrayList的add方法抛异常UnsupportedOperationException
调用ArrayList的add方法抛异常UnsupportedOperationException 对于一些想要把数组转成List的需求,可能会使用到Arrays.asList()获取List对象,但 ...
- netcore高级知识点,内存对齐,原理与示例
最近几年一直从事物联网开发,与硬件打交道越来越多,发现越接近底层开发对性能的追求越高,毕竟硬件资源相对上层应用来实在是太缺乏了.今天想和大家一起分享关于C#中的内存对齐,希望通过理解和优化内存对齐,可 ...
- 声明式 Shadow DOM:简化 Web 组件开发的新工具
在现代 Web 开发中,Web 组件已经成为创建模块化.可复用 UI 组件的标准工具.而 Shadow DOM 是 Web 组件技术的核心部分,它允许开发人员封装组件的内部结构和样式,避免组件的样式和 ...
- P4036 [JSOI2008] 火星人
#include <bits/stdc++.h> #define int long long using namespace std; int len; int m; int rt = 0 ...
- 使用GrabCut做分割
主要完成了界面化设计,代码如下 import cv2 as cv import numpy as np import sys from PyQt5.Qt import * class MyWedige ...
- EBS GL 当前职责有访问权限的所有账套
CREATE OR REPLACE VIEW CUX_GL_ACCESS_LEDGER_V AS SELECT L.LEDGER_ID,L.NAME,L.LEDGER_CATEGORY_CODE FR ...
- 洛谷P1596水坑计数
[USACO10OCT] Lake Counting S 题目链接 题面翻译 由于近期的降雨,雨水汇集在农民约翰的田地不同的地方.我们用一个 \(N\times M(1\leq N\leq 100, ...
- MYSQL 批量删除以特定前缀开头的表
前言 这是工作中确实会用到,比如分库分表后有t_order_01.t_order_02.t_order_03...t_order_08 这样的表. 测试过程中造了大量数据进行测试,其中可能含有部分脏数 ...
- Machine Learning Week_1 Welcome
目录 0 Welcome 0.1 Video: Welcome to Machine Learning! Transcript unfamiliar words 0.2 Reading: Machin ...
- 一文彻底弄懂MySQL的优化
在企业级 Web 开发中,MySQL 优化是至关重要的,它直接影响系统的响应速度.可扩展性和整体性能.下面从不同角度,列出详细的 MySQL 优化技巧,涵盖查询优化.索引设计.表结构设计.配置调整等方 ...