1) newScheduledThreadPool

newScheduledThreadPool-任务调度线程池是指,增加任务延时执行/定时执行功能的线程池。
在【任务调度线程池】功能加入之前,可以使用java.util.Timer来实现定时功能,Timer的优点在于简单易用,但由于所有任务都是同一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都会影响到后面的任务。
相比于Timer,ScheduledThreadPool可以做到多线程执行任务,不会出现单线程串行执行任务的情况,而且前一任务出现异常,也不会影响后续任务。
ScheduledThreadPool提交task的方式为:pool.scheduler(Runnable/Callable对象,延时时间-delay,延时单位-TimeUnit)

延时执行线程任务:

  1. import java.util.concurrent.ExecutorService;
  2. import java.util.concurrent.Executors;
  3. import java.util.concurrent.ScheduledExecutorService;
  4. import java.util.concurrent.TimeUnit;
  5. public class TestScheduledPool {
  6. public static void main(String[] args) {
  7. ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
  8. pool.schedule(()->{
  9. System.out.println("fuckxueshu");
  10. try {
  11. Thread.sleep(1000);
  12. } catch (InterruptedException e) {
  13. e.printStackTrace();
  14. }
  15. },1,TimeUnit.SECONDS);
  16. pool.schedule(()->{
  17. System.out.println("fuckxueshu");
  18. },1,TimeUnit.SECONDS);
  19. }
  20. }

定时执行线程任务:

  1. import java.util.concurrent.ExecutorService;
  2. import java.util.concurrent.Executors;
  3. import java.util.concurrent.ScheduledExecutorService;
  4. import java.util.concurrent.TimeUnit;
  5. public class TestScheduledPool {
  6. public static void main(String[] args) {
  7. ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
  8. System.out.println("start...");
  9. pool.scheduleAtFixedRate(()->{
  10. System.out.println("running");
  11. },1,1,TimeUnit.SECONDS);
  12. }
  13. }

pool.scheduleAtFixedRate()方法,间隔固定时间来执行一次任务,上例代码效果是初始延迟1秒,每隔1秒执行一次任务。

2) 正确处理线程池异常

当任务提交给线程池后,如果执行任务中存在异常,线程池默认既不会抛出异常也不会将控制信息显示,这由线程池的内部实现决定。
如果希望线程池能够处理任务中的异常,可以通过两种方式实现(适用于所有线程池):

1、任务本身捕获异常

try-catch块将异常语句包裹,出现异常则由catch块捕捉。

  1. public class TestScheduledPool {
  2. public static void main(String[] args) {
  3. ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
  4. pool.scheduleAtFixedRate(()->{
  5. System.out.println("running");
  6. try {
  7. int i=1/0;
  8. }catch (Exception e){
  9. e.printStackTrace();
  10. }
  11. },1,1,TimeUnit.SECONDS);
  12. }

2、以Future对象的形式返回任务结果

线程池使用submit等方法向线程池提交任务时,任务是存在返回值的,并使用Future对象接收返回值。通过这种方式实现的任务,如果任务中出现异常,当通过Future类的get方法获取结果时,控制台会报告错误信息,因为任务出现异常,无法返回值。

  1. import java.util.concurrent.*;
  2. public class TestScheduledPool {
  3. public static void main(String[] args) throws ExecutionException, InterruptedException {
  4. ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
  5. Future<Boolean> future = pool.submit(()->{
  6. System.out.println("running");
  7. int i=1/0;
  8. return true;
  9. });
  10. future.get();
  11. }
  12. }

主线程执行到 future.get() 方法时,由于获取不到线程池返回的任务结果,会报以下错误:
image.png