当前位置:   article > 正文

java 周期任务_JAVA线程池ScheduledExecutorService周期性地执行任务 与单个Thread周期性执行任务的异常处理...

scheduledexecutorservice.scheduleatfixedrate java.lang.illegalargumentexcept

本文记录:

1,使用ScheduledExecutorService的 scheduleAtFixedRate 方法执行周期性任务的过程,讨论了在任务周期执行过程中出现了异常,会导致周期任务失败。

2,使用普通的Thread类来执行任务,在main线程中周期性创建线程,提交任务。然后,使用UncaughtExceptionHandler来处理异常。

一,正常任务执行

负责执行任务的线程类如下:(一个计算阶乘的任务,计算5以上的阶乘,就会抛出异常)

1 public class FactorialCalc implementsRunnable {2

3 privateInteger number;4

5 publicFactorialCalc(Integer number) {6 this.number =number;7 }8

9 public voidrun() {10

11 int result = 1;12

13 if (number == 0) {14 System.out.println("0!=" + "1");15 }16

17 if (number > 5) {18 System.out.println("exception");19 throw new IllegalArgumentException(">5");20 }21

22 for(int i = 1; i <= number; i++) {23 result *=i;24

25 }26 System.out.println(number + "!=" +result);27 }28 }

测试的Main类如下:

1 public classMainPeriod {2

3 public static voidmain(String[] args) {4

5 ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);6

7 FactorialCalc task1 = new FactorialCalc(6);8 FactorialCalc task2 = new FactorialCalc(3);9

10 ScheduledFuture> result = executorService.scheduleAtFixedRate(task1, 0, 1, TimeUnit.SECONDS);11 //ScheduledFuture> result = executorService.scheduleAtFixedRate(task2, 0, 2, TimeUnit.SECONDS);

12

13 try{14 TimeUnit.SECONDS.sleep(5);15 executorService.shutdown();16 } catch(InterruptedException e) {17 e.printStackTrace();18 }19 }20 }

ScheduledFuture> result = executorService.scheduleAtFixedRate(task1, 0, 1, TimeUnit.SECONDS);

提交一个Runnable任务,延迟为0,每1秒钟执行一次。

二,线程 执行过程中出现异常

当提交 task1 时,线程在执行过程中会抛出异常。

FactorialCalc task1 = new FactorialCalc(6);//计算6的阶乘,6大于5

ScheduledFuture> result = executorService.scheduleAtFixedRate(task1, 0, 1, TimeUnit.SECONDS);

此时,如果注释掉 //executorService.shutdown(); 则线程池不会中止,因为这是一个线程池,所有的异常都由线程池catch住了。但是由于线程执行过程中抛出了异常,任务也不会周期性地执行了。参考JDK里面的scheduleAtFixedRate注释:

* If any execution of the task

* encounters an exception, subsequent executions are suppressed.public ScheduledFuture>scheduleAtFixedRate(Runnable command,longinitialDelay,longperiod,

TimeUnit unit);

2ec9da6fff97b234032dc9fa2fef8f29.png

三,关闭线程池 ,执行 executorService.shutdown() 语句

若线程池线程 执行任务过程中抛出了异常,但是在 主线程中 执行了executorService.shutdown() 语句,则会正常关闭 线程池。

四,总结

使用ScheduledExecutorService的 scheduleAtFixedRate 方法执行周期性任务时,如果任务一直正常执行,则任务会按设定的执行周期一直在运行(前提是,主线程内不要调用executorService.shutdown() ,比如需要 执行 永久性的周期性任务,那就不能调用 executorService.shutdown() )。

如果任务在某次执行过程中抛出了异常,则周期性任务会被中断,后续也不会再生成任务了,如果主线程 也没有 调用 executorService.shutdown() ,那线程池就不会关闭了。

五,使用Thread类执行任务,在Main线程中通过while循环周期性提交任务,使用UncaughtExceptionHandler来处理异常

1 importjava.util.Random;2 importjava.util.concurrent.TimeUnit;3

4 public classMain {5

6 public static voidmain(String[] args) {7

8 Random rand = newRandom();9

10 while(true){11 int number = rand.nextInt(10);12 Thread t = new Thread(newFactorialCalc(number));13 t.setUncaughtExceptionHandler(newExceptionHandler());14 t.start();15 try{16 System.out.println("sleep 4s for next task");17 TimeUnit.SECONDS.sleep(4);18 }catch(InterruptedException e){19

20 }21 }22 }23 }

在main方法中使用一个while(true)循环,周期性地创建线程 提交任务。

第12-13行,每创建一个线程,调用setUncaughtExceptionHandler方法设置异常处理。关于异常处理,可参考:JAVA线程未捕获异常处理

第15-18行,线程每隔4s提交一次任务,从而实现任务的周期性执行。

异常处理类ExceptionHandler类实现了UncaughtExceptionHandler接口,然后在uncaughtException方法里面定义具体的异常处理过程即可。

importjava.lang.Thread.UncaughtExceptionHandler;public class ExceptionHandler implementsUncaughtExceptionHandler{

@Overridepublic voiduncaughtException(Thread t, Throwable e) {

System.out.println("illegal exception: 计算的阶乘大于5了," +e.getMessage());

}

}

与线程池方式相比 ,这种方式是每个周期,都要new一个线程。而线程池则是每个周期new一个任务,把任务提交给线程池即可。

原文:http://www.cnblogs.com/hapjin/p/7616068.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/83848
推荐阅读
相关标签
  

闽ICP备14008679号