Java 如何使用ScheduledExecutorService重新安排任务?

Java 如何使用ScheduledExecutorService重新安排任务?,java,Java,我在java文档中看到了这一点:,它说 如果任务的任何执行 遇到异常,随后 死刑被禁止 我不希望在我的应用程序中发生这种情况。即使我看到异常,我也总是希望后续执行发生并继续。如何从ScheduledExecutorService中获得此行为,请使用try/catch围绕Callable.call方法或Runnable.run方法 例如: 请注意,捕获除编译器告诉您的内容之外的任何内容(我的示例中的IOException)都不是一个好主意,但有时,如果您正确处理它,这听起来像是其中之一 请记住,像

我在java文档中看到了这一点:,它说

如果任务的任何执行 遇到异常,随后 死刑被禁止


我不希望在我的应用程序中发生这种情况。即使我看到异常,我也总是希望后续执行发生并继续。如何从
ScheduledExecutorService

中获得此行为,请使用try/catch围绕Callable.call方法或Runnable.run方法

例如:

请注意,捕获除编译器告诉您的内容之外的任何内容(我的示例中的IOException)都不是一个好主意,但有时,如果您正确处理它,这听起来像是其中之一


请记住,像错误这样的事情是非常糟糕的-虚拟机内存不足等。。。所以要小心处理它们(这就是为什么我把它们分成自己的处理程序,而不是只做catch(final-Throwable-ex)之类的事情)。

我也有同样的问题。我还尝试了run()方法中的try块,但它不起作用

所以我做了一件目前为止有效的事情:

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

public class Test2 {

    static final ExecutorService pool = Executors.newFixedThreadPool(3);

    static final R1 r1 = new R1();
    static final R2 r2 = new R2();

    static final BlockingQueue deadRunnablesQueue = new LinkedBlockingQueue<IdentifiableRunnable>();

    static final Runnable supervisor = new Supervisor(pool, deadRunnablesQueue);

    public static void main(String[] args) {
        pool.submit(r1);
        pool.submit(r2);
        new Thread(supervisor).start();
    }

    static void reSubmit(IdentifiableRunnable r) {
        System.out.println("given to an error, runnable [" + r.getId()
                + "] will be resubmited");
        deadRunnablesQueue.add(r);
    }

    static interface IdentifiableRunnable extends Runnable {
        String getId();
    }

    static class Supervisor implements Runnable {
        private final ExecutorService pool;
        private final BlockingQueue<IdentifiableRunnable> deadRunnablesQueue;

        Supervisor(final ExecutorService pool,
                final BlockingQueue<IdentifiableRunnable> deadRunnablesQueue) {
            this.pool = pool;
            this.deadRunnablesQueue = deadRunnablesQueue;
        }

        @Override
        public void run() {
            while (true) {
                IdentifiableRunnable r = null;
                System.out.println("");
                System.out
                        .println("Supervisor will wait for a new runnable in order to resubmit it...");
                try {
                    System.out.println();
                    r = deadRunnablesQueue.take();
                } catch (InterruptedException e) {
                }
                if (r != null) {
                    System.out.println("Supervisor got runnable [" + r.getId()
                            + "] to resubmit ");
                    pool.submit(r);
                }
            }
        }
    }

    static class R1 implements IdentifiableRunnable {
        private final String id = "R1";
        private long l;

        @Override
        public void run() {
            while (true) {
                System.out.println("R1 " + (l++));
                try {
                    Thread.currentThread().sleep(5000);
                } catch (InterruptedException e) {
                    System.err.println("R1 InterruptedException:");
                }
            }
        }

        public String getId() {
            return id;
        }
    }

    static class R2 implements IdentifiableRunnable {
        private final String id = "R2";
        private long l;

        @Override
        public void run() {
            try {
                while (true) {
                    System.out.println("R2 " + (l++));
                    try {
                        Thread.currentThread().sleep(5000);
                    } catch (InterruptedException e) {
                        System.err.println("R2 InterruptedException:");
                    }
                    if (l == 3) {
                        throw new RuntimeException(
                                "R2 error.. Should I continue to process ? ");
                    }
                }
            } catch (final Throwable t) {
                t.printStackTrace();
                Test2.reSubmit(this);
            }
        }

        public String getId() {
            return id;
        }
    }

}
import java.util.concurrent.BlockingQueue;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.LinkedBlockingQueue;
公共类Test2{
静态最终ExecutorService池=Executors.newFixedThreadPool(3);
静态最终R1=新R1();
静态最终R2=新R2();
静态最终阻塞队列deadRunnablesQueue=新建LinkedBlockingQueue();
静态最终可运行管理器=新管理器(池、DeadRunnableQueue);
公共静态void main(字符串[]args){
提交(r1);
提交(r2);
新线程(主管).start();
}
静态无效重新提交(可识别可运行r){
System.out.println(“给定一个错误,runnable[”+r.getId()
+“]将重新提交”);
deadRunnablesQueue.add(r);
}
静态接口可识别Runnable扩展Runnable{
字符串getId();
}
静态类主管实现Runnable{
私人最终服务池;
私有最终阻塞队列deadRunnablesQueue;
主管(最终服务池),
最终阻塞队列(可运行队列){
this.pool=pool;
this.deadRunnablesQueue=deadRunnablesQueue;
}
@凌驾
公开募捐{
while(true){
可识别可运行r=null;
System.out.println(“”);
系统输出
.println(“主管将等待新的runnable以便重新提交…”);
试一试{
System.out.println();
r=deadRunnablesQueue.take();
}捕捉(中断异常e){
}
如果(r!=null){
System.out.println(“主管已运行[”+r.getId())
+“]重新提交”);
提交(r);
}
}
}
}
静态类R1实现可识别的可运行{
私有最终字符串id=“R1”;
私人长l;
@凌驾
公开募捐{
while(true){
System.out.println(“R1”+(l++”);
试一试{
Thread.currentThread().sleep(5000);
}捕捉(中断异常e){
System.err.println(“R1 InterruptedException:”);
}
}
}
公共字符串getId(){
返回id;
}
}
静态类R2实现可识别的Runnable{
私有最终字符串id=“R2”;
私人长l;
@凌驾
公开募捐{
试一试{
while(true){
System.out.println(“R2”+(l++”);
试一试{
Thread.currentThread().sleep(5000);
}捕捉(中断异常e){
System.err.println(“R2 InterruptedException:”);
}
如果(l==3){
抛出新的运行时异常(
“R2错误..我应该继续处理吗?”);
}
}
}捕获(最终可丢弃的t){
t、 printStackTrace();
测试2.重新提交(本);
}
}
公共字符串getId(){
返回id;
}
}
}
您可以尝试注释掉Test2。重新提交(此)以查看如果没有它,R2将停止工作。

try class from,ToBubeer建议的换行操作是:

import com.jcabi.log.VerboseRunnable;
Runnable runnable = new VerboseRunnable(
  Runnable() {
    public void run() { 
      // do business logic, may Exception occurs
    }
  },
  true // it means that all exceptions will be swallowed and logged
);
现在,当任何人调用
runnable.run()
时,都不会抛出异常。相反,它们会被吞并并记录(到SLF4J)。

如果您只希望后续执行发生并在异常发生后继续,那么此代码应该可以工作

 ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();    

 Runnable task = new Runnable() {      
  @Override
  public void run() {
   try{
      System.out.println(new Date() + " printing");
      if(true)
        throw new RuntimeException();

   } catch (Exception exc) {
      System.out.println(" WARN...task will continiue"+ 
            "running even after an Exception has araised");
    }
  }      
};

executor.scheduleAtFixedRate(task, 0, 3, TimeUnit.SECONDS);
如果发生了除
异常
之外的
可丢弃
,您可能不希望执行后续执行

这是输出

11月23日星期五12:09:38 JST 2012打印
\u警告…任务将 即使在11月23日星期五引发异常后仍继续运行
12:09:41 JST 2012打印
\u警告…任务将继续运行 即使在引发异常后
周五11月23日12:09:44 JST 2012 打印
\u警告…即使在 异常已引发
周五11月23日12:09:47 JST 2012打印
_警告…即使引发异常,任务仍将继续运行


请注意,如果您在重复的计划任务中没有捕捉到throwable,并且OOME确实发生,您将永远不会发现它(除非有人在ScheduledFuture上调用get()并记录ExecutionExceptionsWell…我猜您必须…ick:-)我会
 ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();    

 Runnable task = new Runnable() {      
  @Override
  public void run() {
   try{
      System.out.println(new Date() + " printing");
      if(true)
        throw new RuntimeException();

   } catch (Exception exc) {
      System.out.println(" WARN...task will continiue"+ 
            "running even after an Exception has araised");
    }
  }      
};

executor.scheduleAtFixedRate(task, 0, 3, TimeUnit.SECONDS);