java - 如何让主线程等待完成 UncaughtExceptionHandler 执行
问题描述
我有以下多线程代码。我希望LatchCode.doStuff()
等到UncaughtExceptionHandler
处理程序完成它的工作,但事实并非如此。我怎么能让主线程等待它。对于某些项目要求,我需要将异常传播给父级,以将错误记录到数据库中(应该在处理结束时发生)。以下是一段代码。
public class LatchExceptionTest {
public static void main(String[] args) {
LatchCode l = new LatchCode();
Cont c = new Cont();
try {
l.doStuff(c);
System.out.println("Main Thread - work completed");
if(!c.err.isEmpty())
throw new Exception(c.err.toString());
} catch (Exception e) {
System.out.println("trace printing start");
System.out.println(c.err.toString()); // log errors to DB
System.out.println("trace printing edn");
}
}
}
class LatchCode {
public void doStuff(final Cont cont) throws RuntimeException, InterruptedException {
System.out.println("Intermediate class start");
try {
Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread th, Throwable ex) {
cont.err.add(ex.getMessage());
}
};
Thread aggregatorThread = new Thread(() -> {
try {
if(cont.err.size() > 0)
return;
System.out.println("AGGREGATOR thread START");
Thread.sleep(3000);
System.out.println("AGGREGATOR thread END");
} catch (Exception e) {
throw new RuntimeException(e);
}
});
CyclicBarrier barrier = new CyclicBarrier(2, aggregatorThread);
AA a = new AA();
BB b = new BB();
CountDownLatch latch = new CountDownLatch(2);
Thread one = new Thread(() -> {
try {
a.doSomething();
} catch (Exception e) {
System.out.println("Exception in 1");
//Thread.currentThread().interrupt();
throw new RuntimeException(e.toString());
} finally {
try {
barrier.await();
} catch (Exception e) {
System.out.println("Exception in 1 finallt");
throw new RuntimeException(e.toString());
} finally {
latch.countDown();
}
}
});
Thread two = new Thread(() -> {
try {
b.doSomething();
} catch (Exception e) {
System.out.println("Exception in 2");
Thread.currentThread().interrupt();
throw new RuntimeException(e);
} finally {
try {
barrier.await();
} catch (Exception e) {
System.out.println("Exception in 2 finallt");
throw new RuntimeException(e);
} finally {
latch.countDown();
}
}
});
one.start();
two.start();
one.setUncaughtExceptionHandler(h);
two.setUncaughtExceptionHandler(h);
latch.await();
} catch (Exception e) {
System.out.println("Exception in caller");
throw new RuntimeException(e);
} finally {
System.out.println("Intermediate class end");
}
}
}
class AA {
public void doSomething() throws Exception {
try {
System.out.println("1 start");
Thread.sleep(1);
throw new Exception("In AA");
} catch (Exception e) {
System.out.println("Exception in AA");
throw new Exception(e.toString());
}
}
}
class BB {
public void doSomething() throws Exception {
try {
System.out.println("2 start");
Thread.sleep(1);
} catch (Exception e) {
System.out.println("Exception in BB");
}
System.out.println("2 end");
}
}
class Cont {
ConcurrentLinkedQueue<String> err = new ConcurrentLinkedQueue<String>();
}
如果AA.doStuff()
并且BB.doStuff()
有记录器睡眠,那么我可以Cont.err
不为空并进入 catch 块。但是如果睡眠时间可以忽略不计,比如 1 毫秒,那么如果阻塞main()
失败并且程序正在执行,就好像没有异常一样。
所以我需要调用线程来等待UncaughtExceptionHandler
完成。有人可以帮忙吗。
提前致谢
解决方案
经过详尽的搜索,找到了以下页面。详细了解 UEH 中的工作原理。 https://bugs.openjdk.java.net/browse/JDK-8153487
摘自上述主题的简短回答:
There is no guarantee that UncaughtExceptionHandlers have run before awaitTermination returns.
It is a pool thread that sets the state to TERMINATED, so it cannot wait for all pool threads to terminate!
It seems unlikely we can make this better. It seems that relying on the UEH in this way is a poor design
推荐阅读
- autobahn - crossbar 路由器在没有 docker 的情况下启动
- email - 确定电子邮件接收者是否为 Outlook / Office 365 以呈现可操作邮件
- javascript - Javascript - 我如何让点击动作只应用于上层元素
- javascript - [已解决]ApexCharts.js:如何为折线图中的轴标签设置固定值
- reactjs - React setState hook异步更新问题
- javascript - 闭包如何在 addEventListener 中工作?
- c - 计算点相交的沿纬度长向量的距离
- sharepoint - 使用 jsom 在 Sharepoint 中获取术语及其子术语
- google-colaboratory - 如何从其他公共驱动器直接将谷歌驱动器文件夹下载到colab而不下载到PC?
- javascript - Reactjs没有显示从状态生成的动态数据