去年年底,我正在运行预定的任务来监视Neo4j集群,而我遇到的问题之一是有时监视会退出。

我最终意识到这是因为RuntimeException被抛出到Runnable方法中,而我没有处理它。 以下代码演示了该问题:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;public class RunnableBlog {public static void main(String[] args) throws ExecutionException, InterruptedException {ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();executor.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + " -> " + System.currentTimeMillis());throw new RuntimeException("game over");}}, 0, 1000, TimeUnit.MILLISECONDS).get();System.out.println("exit");executor.shutdown();}
}

如果运行该代码,我们将看到RuntimeException,但是执行器不会退出,因为线程在没有通知的情况下就死了:

Exception in thread "main" pool-1-thread-1 -> 1391212558074
java.util.concurrent.ExecutionException: java.lang.RuntimeException: game overat java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:252)at java.util.concurrent.FutureTask.get(FutureTask.java:111)at RunnableBlog.main(RunnableBlog.java:11)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:601)at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.lang.RuntimeException: game overat RunnableBlog$1.run(RunnableBlog.java:16)at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:351)at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:178)at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)at java.lang.Thread.run(Thread.java:722)

当时我最终添加了一个try catch块并打印如下异常:

public class RunnableBlog {public static void main(String[] args) throws ExecutionException, InterruptedException {ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();executor.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {try {System.out.println(Thread.currentThread().getName() + " -> " + System.currentTimeMillis());throw new RuntimeException("game over");} catch (RuntimeException e) {e.printStackTrace();}}}, 0, 1000, TimeUnit.MILLISECONDS).get();System.out.println("exit");executor.shutdown();}
}

据我所知,这允许异常被识别,并且执行Runnable的线程不会死亡。

java.lang.RuntimeException: game over
pool-1-thread-1 -> 1391212651955at RunnableBlog$1.run(RunnableBlog.java:16)at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:351)at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:178)at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)at java.lang.Thread.run(Thread.java:722)
pool-1-thread-1 -> 1391212652956
java.lang.RuntimeException: game overat RunnableBlog$1.run(RunnableBlog.java:16)at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:351)at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:178)at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)at java.lang.Thread.run(Thread.java:722)
pool-1-thread-1 -> 1391212653955
java.lang.RuntimeException: game overat RunnableBlog$1.run(RunnableBlog.java:16)at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:351)at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:178)at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)at java.lang.Thread.run(Thread.java:722)

这很好,使我能够继续监视集群。

但是,我最近开始阅读“ Java Concurrency in Practice ”(购买后仅6年!),并意识到这可能不是处理RuntimeException的正确方法。

public class RunnableBlog {public static void main(String[] args) throws ExecutionException, InterruptedException {ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();executor.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {try {System.out.println(Thread.currentThread().getName() + " -> " + System.currentTimeMillis());throw new RuntimeException("game over");} catch (RuntimeException e) {Thread t = Thread.currentThread();t.getUncaughtExceptionHandler().uncaughtException(t, e);}}}, 0, 1000, TimeUnit.MILLISECONDS).get();System.out.println("exit");executor.shutdown();}
}

我认为这两种方法之间没有太大区别,所以如果有人可以向我解释为什么这种方法比我以前的捕获异常并打印堆栈跟踪的方法更好的话,那将是一个很好的选择。

参考: Java:通过Mark Needham博客博客的JCG合作伙伴 Mark Needham 处理可运行的RuntimeException 。

翻译自: https://www.javacodegeeks.com/2014/02/java-handling-a-runtimeexception-in-a-runnable.html

Java:在Runnable中处理RuntimeException相关推荐

  1. java中runnable_Java:在Runnable中处理RuntimeException

    java中runnable 去年年底,我正在运行预定的任务来监视Neo4j集群,而我遇到的问题之一是有时会退出监视. 最终我意识到这是因为RuntimeException被抛出到Runnable方法中 ...

  2. Java中常见RuntimeException与其他异常表及Exception逻辑关系详解

    Java中常见RuntimeException与其他异常表及Exception逻辑关系详解 前言 常见`RuntimeException` 其他错误类型 `Error`类 `Exception`类 E ...

  3. java中关于RuntimeException和非RuntimeException

    一次偶然的刷题中,看到CSDN中关于RuntimeException和非RuntimeException的分类中,有几篇文章是把他糅杂在一起的,并没有分类,误导了我,为此我专门去搜索研究了一下. 常见 ...

  4. Java笔记(学习中。。)

    Java笔记 eclipse的使用 常用的dos指令 预备知识 基本语法 变量 关于字符型 关于String 进制转换 运算符 流程控制 数组 数组的内存解析: 数组的Arrays工具类 面向对象 对 ...

  5. Akka 系列(五):Java 和 Scala 中的 Future

    随着CPU的核数的增加,异步编程模型在并发领域中的得到了越来越多的应用,由于Scala是一门函数式语言,天然的支持异步编程模型,今天主要来看一下Java和Scala中的Futrue,带你走入异步编程的 ...

  6. Java 线程池中的线程复用是如何实现的?

    前几天,技术群里有个群友问了一个关于线程池的问题,内容如图所示: 关于线程池相关知识可以先看下这篇:为什么阿里巴巴Java开发手册中强制要求线程池不允许使用Executors创建? 那么就来和大家探讨 ...

  7. Java并发编程中的若干核心技术,向高手进阶

    来源:http://www.jianshu.com/p/5f499f8212e7 引言 本文试图从一个更高的视角来总结Java语言中的并发编程内容,希望阅读完本文之后,可以收获一些内容,至少应该知道在 ...

  8. Java实现Runnable接口创建多线程

    Java实现Runnable接口创建多线程 通过继承Thread类,实现多线程,但是,这种方式有一定的局限性,因为,Java中只支持单继承,一个类一旦继承了某个父类,就无法再继承Thread类 比如, ...

  9. Java多线程编程中Future模式的详解

    转载自 https://www.cnblogs.com/winkey4986/p/6203225.html Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker ...

最新文章

  1. JavaScript 简史
  2. 作为“山寨版脸书”Reels在网站推广中真的要和Tik Tok死磕?
  3. HTML5新特征、窍门和技术(16~20)
  4. 信息学奥赛一本通(1323:【例6.5】活动选择)
  5. 所有controller interceptor_阿里二面:filter、interceptor、aspect应如何选择?很多人中招...
  6. 多目标进化优化 郑金华pdf_简化审批流程 金华首张以“告知承诺制”审批的医疗器械经营许可证发放...
  7. linux下大于2T的硬盘使用方法
  8. 数据结构和算法——中序线索化二叉树
  9. PHP调用微信发放现金红包接口
  10. maya2022|autodesk maya 2022新功能介绍
  11. c语言交通处罚单系统主函数,C语言课程设计交通处罚单管理系统.doc
  12. css-图片旋转木马3D效果
  13. mac 苹果系统安装pygame环境插件
  14. 投影向量=投影长度乘以单位向量
  15. 电脑怎么连接隐藏的无线WiFi ?
  16. C++11 学习笔记(持续更新)
  17. 2021年中国汽车产量、销量及汽车制造业发展趋势分析[图
  18. python3爬虫图片_【已下线】Python3 实现淘女郎照片爬虫
  19. precede和previous_Previous是什么意思?
  20. 学会这个神器和技巧,低代码开发高端可视化大屏

热门文章

  1. vue的基本项目结构
  2. ajax调用后台java类_ajax调用java后台方法是什么
  3. python遗传算法工具箱的使用_遗传算法的python实现,非常值得看的一篇文章
  4. CGLIB依赖ASM(关于java字节码框架ASM的学习)
  5. removeAll throws java.lang.UnsupportedOperationException
  6. vertx rest 跨域_Vertx编程风格:您的React式Web Companion REST API解释了
  7. cli parser_Java命令行界面(第27部分):cli-parser
  8. rest web服务_在WildFly的REST Web服务中与Jackson的双向关系
  9. finally块_如何从finally块访问方法的结果值
  10. 带有HttpClient的自定义HTTP标头