【问题标题】:Why doesn't my Thread create a new one when it catches an Exception?为什么我的线程在捕获异常时不创建一个新线程?
【发布时间】:2020-11-01 22:38:08
【问题描述】:

所以我有一个这样运行的线程:

Runnable runnable = new Runnable() {
                        @Override
                        public void run() {
                            System.out.println("redo groupMonitor ... ");
                            if (redogmSafer < 1) {
                                groupMonitor.run(remoteHost, port);
                            } else {
                            }
                            redogmSafer = 100;
                        }
                    };
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(runnable, 0, delayStart, TimeUnit.MILLISECONDS);

if (redogmSafer < 1) {
} else {
    service.shutdown();
    service.shutdownNow();
    redogmSafer = 0;
}

我想再次run() Thread,在它由于异常或其他原因退出之后(发生所有 4-5 小时)。

我尝试过shutdown()shutdownNow(),但这也无济于事。就像 Java 在启动和关闭后不想重做线程......

【问题讨论】:

  • 没错。一旦线程终止,您将无法再次启动它。但是,自从您使用scheduleAtFixedRate 以来,问题是什么?稍后执行 get 的任务。请edit您的问题包含您拥有的完整源代码作为minimal reproducible example
  • 或许你应该解释一下groupMonitor.run(remoteHost, port)

标签: java


【解决方案1】:

你可以像这样创建一个新线程:

Thread newThread = new Thread(runnable);

newThread.start();

或使用 ExecutorService:

ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(runnable);

但是您已经在使用 ScheduledExecutorService 来完成这项工作。

【讨论】:

  • Executors 框架的发明是为了替代手动处理线程。
【解决方案2】:

用 try-catch 包装你的 Runnable / Callable 代码

ScheduledExecutorService 在收到 ThrowableExceptionError)后会停止进一步的调度。这种停止是静默的,没有错误报告,也没有消息或日志记录。

因此,您应该着眼于预防问题而不是解决问题。预防措施是用 try-catch 包装你的 Runnable / Callable 代码。

只要没有Throwable冒泡调用堆栈到达调度的执行器服务,调度就会继续。

Runnable runnable = new Runnable() {
                        @Override
                        public void run() {
                            try{
                                System.out.println("redo groupMonitor ... ");
                                if (redogmSafer < 1) {
                                    groupMonitor.run(remoteHost, port);
                                } else { 
                                    …
                                }
                                redogmSafer = 100;
                            } catch ( Exception e ) { … }
                        }
                    };

您是否捕获 ThrowableException 或更具体的异常取决于您和您的团队根据您的情况来决定。

这个话题已经在 Stack Overflow 上讨论过多次。搜索以了解更多信息。具体见ScheduledExecutorService Exception handling

【讨论】:

  • 所以一旦方法 groupMonitor.run() 发生异常,它会再次被调用,对吧?
  • 我需要runnable在每次方法返回时调用groupMonitor.run(),因为连接丢失ETC等异常。
  • @aqwertyyyz 您的Runnable 对象的run 方法将在经过您在调用scheduleAtFixedRate 中指定的时间后每隔一段时间运行一次。如果超过 500 毫秒,那么每半秒 Runnable 对象的 run 方法就会执行一次。在您的情况下,如果您的 if 测试通过,groupMonitor.run 就会执行。该方法的作用,我无法解决,因为您没有解释groupMonitor.run(remoteHost, port)。但我可以说,如果在该方法的其中一次执行期间抛出了 Exception 而没有被捕获,那将是 runnable 的 run 的最后一次执行。
  • 我会更新答案,让这三种方法的工作更加清晰
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-31
相关资源
最近更新 更多