Java 从UncaughtExceptionHandler中重新执行任务?

Java 从UncaughtExceptionHandler中重新执行任务?,java,multithreading,Java,Multithreading,我看到了一些关于这些方面的讨论,但没有对我的问题给出具体的答案。我想在线程因未捕获异常而死亡时重新启动任务。从垂死线程上的UncaughtExceptionHandler集合中调用pool.execute(runnable)安全吗 理想情况下,如果throwable是一个RuntimeException,我只想将runnable重新提交到池中,例如 pool = Executors.newFixedThreadPool(monitors.size(), new ThreadFactory()

我看到了一些关于这些方面的讨论,但没有对我的问题给出具体的答案。我想在线程因未捕获异常而死亡时重新启动任务。从垂死线程上的UncaughtExceptionHandler集合中调用pool.execute(runnable)安全吗

理想情况下,如果throwable是一个RuntimeException,我只想将runnable重新提交到池中,例如


pool = Executors.newFixedThreadPool(monitors.size(), new ThreadFactory() {
    @Override
    public Thread newThread(Runnable r) {
        Thread thread = new Thread(r);
        threadMap.put(thread, (Monitor)r);
        thread.setName(((Monitor)r).getClusterName() + "-monitor");
        thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread th, Throwable t) {
                logger.error("Uncaught exception in thread: " + th.getName(), t);
                if (t instanceof RuntimeException) {
                    Monitor m = threadMap.get(th);
                    if (m != null && m.runCount() < restartMax) {
                        logger.error("Restarting monitor due to uncaughtException: " + m.getClusterName());
                        pool.execute(m);
                    }                        }
            }                   
        });
        return thread;
    }           
});

pool=Executors.newFixedThreadPool(monitors.size(),newThreadFactory()){
@凌驾
公共线程newThread(可运行的r){
螺纹=新螺纹(r);
threadMap.put(线程,(监视器)r);
setName(((Monitor)r.getClusterName()+“-Monitor”);
setUncaughtExceptionHandler(新的UncaughtExceptionHandler(){
@凌驾
公共无效未捕获异常(线程th,可丢弃的t){
错误(“线程中未捕获的异常:+th.getName(),t);
if(运行时异常的t实例){
监视器m=threadMap.get(th);
如果(m!=null&&m.runCount()
有没有更好或更安全的方法


谢谢

最安全的选择是只抛出致命的运行时异常。如果可以安全地忽略运行时异常,为什么不捕获并继续

看起来你的线程映射就像一个ThreadLocal,一旦一个任务使用了你所有的restartMax,它就再也不会重新启动一个任务了

我将这样做的方式是包装正在执行的Runnable

public void submit(final Runnable runnable, final int restartMax) {
    pool.submit(new Runnable() {
       public void run() {
           for(int i=0;i<restartMax;i++)
               try {
                   runnable.run();
                   break;
               } catch (Exception e) {
                   log.error("Exception", e);
               }
       }
    }
 }
public void提交(final Runnable Runnable,final int restartMax){
pool.submit(新的Runnable(){
公开募捐{

对于(int i=0;i来说,最安全的选择是只抛出致命的运行时异常。如果可以安全地忽略运行时异常,为什么不捕获并继续

看起来你的线程映射就像一个ThreadLocal,一旦一个任务使用了你所有的restartMax,它就再也不会重新启动一个任务了

我将这样做的方式是包装正在执行的Runnable

public void submit(final Runnable runnable, final int restartMax) {
    pool.submit(new Runnable() {
       public void run() {
           for(int i=0;i<restartMax;i++)
               try {
                   runnable.run();
                   break;
               } catch (Exception e) {
                   log.error("Exception", e);
               }
       }
    }
 }
public void提交(final Runnable Runnable,final int restartMax){
pool.submit(新的Runnable(){
公开募捐{

对于(int i=0;i您的代码示例无法完成您试图解决的任务。传递给ThreadFactory的runnable不是您的任务runnable,而是ThreadPoolExecutor使用的内部runnable

您可能想考虑重写后继执行()方法。该方法将始终被调用,第一个参数将是可运行的,第二个(可抛出的)参数将包含未被排除的异常。如果任务由您使用FutureTask显式包装或通过submit()间接包装,则不会报告异常。因此,afterExecute()只能通过execute()进行提交

protectedvoid afterExecute(可运行的r、可丢弃的t){
super.afterExecute(r,t);
如果(t!=null){
监视器m=(监视器)r;
if(m.runCount()
您的代码示例无法完成您试图解决的任务。传递给ThreadFactory的runnable不是您的任务runnable,而是ThreadPoolExecutor使用的内部runnable

您可能想考虑重写后继执行()方法。该方法将始终被调用,第一个参数将是可运行的,第二个(可抛出的)参数将包含未被排除的异常。如果任务由您使用FutureTask显式包装或通过submit()间接包装,则不会报告异常。因此,afterExecute()只能通过execute()进行提交

protectedvoid afterExecute(可运行的r、可丢弃的t){
super.afterExecute(r,t);
如果(t!=null){
监视器m=(监视器)r;
if(m.runCount()
是的,我立即遇到了这个问题。目前我使用的是一个传统的新线程/setUncaughtExceptionHandler/start序列。你无法从线程访问Runnable,这似乎既奇怪又短视。我将研究你的建议。我既不使用FutureTask也不使用submit,所以这应该有效。谢谢!即使线程是使用传入的runnable创建的,请注意,触发线程创建的只是您的第一个任务。线程将是长期的,并且运行多个任务。因此,您将无法可靠地获取导致RuntimeException的实际runnable。是的,我立即遇到了这个问题。目前我'我使用的是传统的新线程/setUncaughtExceptionHandler/start序列。您无法从线程访问Runnable似乎既奇怪又短视。我将研究您的建议。我不使用FutureTask也不使用submit,因此这应该可以工作。谢谢!即使线程是使用传入的Runnable创建的,请注意,它只是触发线程创建的第一个任务。线程将长期存在并运行多个任务。因此,您将无法可靠地获取导致RuntimeException的实际runnable。threadMap只是允许