用LockSupport解Leetcode1116并发题,请教下哪里出了问题
问题:
死磕了2天了,不弄明白切鸡儿。大概是在几百次运行后会有明显的同步问题导致结果错误,有时也会莫名其妙的阻塞住。不知道老哥们有何高见,换解法就不必了~
我的解法:
main方法测试用了输出重定向,然后获取打印值进行判断,和期望值不符则break。同时还依赖一个把类似Consumer函数封装成Runnable并try catch异常的接口,嫌麻烦可以自己写测试。
public class Solution1116 {
static CountDownLatch cdl = new CountDownLatch(3);
public static void main(String[] args) {
ZeroEvenOdd zeo = new ZeroEvenOdd(9);
// 重定向输出流相关操作
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
PrintStream old = System.out;
System.setOut(ps);
// 初始化线程和3个Runnable
IntConsumer ic = System.out::print;
ExecutorService es = Executors.newFixedThreadPool(3);
Runnable r0 = ConsumerCatch.runnableWrap(zeo::zero, ic); // 需要ConsumerCatch接口的支持
Runnable r1 = ConsumerCatch.runnableWrap(zeo::odd, ic);
Runnable r2 = ConsumerCatch.runnableWrap(zeo::even, ic);
while (true) {
es.submit(r0);
es.submit(r1);
es.submit(r2);
try {
cdl.await(); // 阻塞主线程
} catch (InterruptedException e) {
e.printStackTrace();
}
// 打印并比对结果
ps.flush();
System.setOut(old);
String s = baos.toString();
System.out.println(s);
if (!s.equals("010203040506070809")) {
break;
}
// 全体重置
baos.reset();
cdl = new CountDownLatch(3);
zeo.reset();
System.setOut(ps);
}
}
private static class ZeroEvenOdd {
private int n;
private volatile int current = 1; // 弃用
private AtomicInteger ai = new AtomicInteger(1);
private volatile Thread t0 = null;
private volatile Thread t1 = null;
private volatile Thread t2 = null;
public ZeroEvenOdd(int n) {
this.n = n;
}
// 测试用,用来使该对象恢复到初始状态
public void reset() {
ai.set(1);
t0 = null;
t1 = null;
t2 = null;
}
// printNumber.accept(x) outputs "x", where x is an integer.
public void zero(IntConsumer printNumber) throws InterruptedException {
t0 = Thread.currentThread();
for (int i = 0; i < n; i++) {
printNumber.accept(0);
while (t1 == null || t2 == null) {} // 自旋保证初始化 + 内存屏障
if ((ai.get() & 1) == 1)
LockSupport.unpark(t1);
else
LockSupport.unpark(t2);
if (i != n - 1)
LockSupport.park();
}
Solution1116.cdl.countDown(); // 仅测试,用来给主线程放行
}
public void even(IntConsumer printNumber) throws InterruptedException {
t2 = Thread.currentThread();
for (int i = 0; i < n / 2; i++) {
LockSupport.park();
printNumber.accept(ai.getAndIncrement());
LockSupport.unpark(t0);
}
Solution1116.cdl.countDown(); // 仅测试,用来给主线程放行
}
public void odd(IntConsumer printNumber) throws InterruptedException {
t1 = Thread.currentThread();
for (int i = 0; i < n - n / 2; i++) {
LockSupport.park();
printNumber.accept(ai.getAndIncrement());
LockSupport.unpark(t0);
}
Solution1116.cdl.countDown(); // 仅测试,用来给主线程放行
}
}
}
main方法所依赖的接口:
主要是为了少写try catch,就整了一个
@FunctionalInterface
public interface ConsumerCatch<T>{
static <T> Runnable runnableWrap(ConsumerCatch<T> ct, T t) {
return () -> {
try {
ct.accept(t);
} catch (Exception e) {
e.printStackTrace();
}
};
}
static <T> Thread threadWrap(ConsumerCatch<T> ct, T t) {
return new Thread(() -> {
try {
ct.accept(t);
} catch (Exception e) {
e.printStackTrace();
}
});
}
void accept(T t) throws Exception;
}相关推荐
高校技术转移办公室人员如何高效开展技术需求挖掘工作?.docx
科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。
科技中介服务机构如何提升服务的专业性与用户粘性?.docx
科技中介服务机构如何提升服务的专业性与用户粘性?
高校技术转移办公室人员在组织科研成果展示时,如何提升推介材料的专业性与吸引力?.docx
科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。
三相并网逆变器无功功率扰动+孤岛检测控制算法仿真【参考文献+仿真】
内容概要:本文系统梳理了一套面向电力电子与新能源并网领域的仿真研究资源,聚焦三相并网逆变器的关键控制技术,涵盖无功功率扰动、孤岛检测算法、低电压穿越(LVRT)、中点电位平衡、虚拟同步发电机(VSG)、下垂控制、模型预测控制(MPC)、准PR控制及LCL滤波器设计等核心技术。资源包含多种逆变器拓扑结构(如T型三电平、Z源、ANPC、四桥臂等)的Simulink仿真模型,并结合扫频法进行正负序阻抗建模与稳定性分析,强调通过复现经典科研案例提升实际科研能力,适用于电力系统稳定性、微电网运行与可再生能源并网等方向的研究与验证。; 适合人群:电力电子、电气工程及其自动化、新能源科学与工程等相关专业的高校研究生、科研人员及从事光伏、储能逆变器开发的工程技术人员,需具备MATLAB/Simulink仿真基础和一定的电力系统控制理论知识。; 使用场景及目标:① 掌握三相并网逆变器在孤岛检测、无功调节、不平衡电网等复杂工况下的先进控制策略设计与仿真方法;② 借助提供的仿真模型与参考文献快速搭建科研平台,用于论文复现、课题开发或项目验证;③ 深入理解VSG、MPC、阻抗建模与下垂控制等关键技术的实现机制与工程应用路径。; 阅读建议:建议结合文中提供的网盘链接与公众号“荔枝科研社”获取完整仿真模型与参考资料,按照目录顺序循序渐进学习,注重理论推导与仿真实践相结合,优先复现基础模型再进行参数优化与创新拓展。
香橙派5-uefi-edk2-spi-flash镜像
香橙派5-uefi-edk2-spi-flash镜像


Java SE
