定时线程池之ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor是jdk提供的基础线程池之一。具有定时执行任务的功能。jgk中另外两种具有定时功能的线程池SingleThreadScheduledExecutor与ScheduledThreadPool实质上都是由ScheduledThreadPoolExecutor来实现的。其继承自基础线程池ThreadPoolExecutor。ScheduledThreadPoolExecuto的构造都是通过调用ThreadPoolExecutor的构造来实现的。ScheduledThreadPoolExecuto的构造提供四种入参,分别为corePoolSize核心线程量,threadFactory线程工厂,handler满载时的拒绝策略(定时线程池一般情况只在线程池处于非Runing状态下接受到新任务时有作用,因为默认的最大线程数是Integer.MAX_VALUE = 2147483647(最大线程数和核心线程数的区别以及何时执行满载策略见ThreadPoolExecutor));定时线程池内部维护了一个内部类DelayedWorkQueue来实现定时任务实现。其类似于DelayedQueue是一种带有元素有效时间的队列。在普通任务的执行方法上ScheduledThreadPoolExecutor和ThreadPoolExecutor类似。其具有几个独特的设置定时任务的方法:

scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit):周期性的执行Runable(延迟时间以上一个任务开始时间开始计算eg:一个线程执行1s,周期为2s,那么它会在0,2,4,6...执行  一个线程执行4s,周期为2s,那么它会在0,4,8,12...执行)

scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit):周期性的执行Runable(延迟时间以上一个任务结束时间开始算。eg:一个线程执行1s,周期为2s,那么它会在0,3,6,9...执行)

schedule(Runnable command,long delay,TimeUnit unit):// 延迟指定时间执行Runable

schedule(Callable<V> callable,long delay,TimeUnit unit):延迟指定时间执行Callable并返回ScheduleFuture

setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean value):线程池关闭之后定时任务是否继续执行,包括scheduleAtFixedRate和scheduleWithFixedDelay。如果有周期任务线程池关闭之后会保持最大线程数(如果关闭时线程还未到达最大线程数依然会建立新线程)(默认false(true:继续,false:放弃))

setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean value):线程池关闭之后是否继续执行delay任务,如果只有延迟任务线程池关闭之后且这个延时任务执行后会销毁所有线程(默认true(true:继续,false:放弃))

具体使用及其它方法的使用见下方代码:

package ThreadPoolExecutor.ScheduledPool;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class ScheduledThreadPoolExecutorDemo {

    public static void main(String[] args) {
        
        /**
         * public class ScheduledThreadPoolExecutor
         *   extends ThreadPoolExecutor
         *   implements ScheduledExecutorService
         */
        ScheduledThreadPoolExecutor ScheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
        /**public ScheduledThreadPoolExecutor(int corePoolSize) {
            super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
                  new DelayedWorkQueue());
            }*/
        ScheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1, Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        /**public ScheduledThreadPoolExecutor(int corePoolSize,
                                       ThreadFactory threadFactory,
                                       RejectedExecutionHandler handler) {
            super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
                  new DelayedWorkQueue(), threadFactory, handler);*/
        ScheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1, Executors.defaultThreadFactory());
        /**public ScheduledThreadPoolExecutor(int corePoolSize,
                                       ThreadFactory threadFactory) {
            super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
                  new DelayedWorkQueue(), threadFactory);
            }*/
        ScheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(5, new ThreadPoolExecutor.CallerRunsPolicy());
        /**public ScheduledThreadPoolExecutor(int corePoolSize,
                                       RejectedExecutionHandler handler) {
            super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
                  new DelayedWorkQueue(), handler);
            }*/
        
        /**
        // 定义自己的拒绝策略
        new RejectedExecutionHandler() {
            
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                
            }
        };*/
        final AtomicInteger i = new AtomicInteger();
        Runnable run1 = new Runnable() {
            
            @Override
            public void run() {
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("A第" + i.incrementAndGet() + "次执行");
            }
        };

        final AtomicInteger i2 = new AtomicInteger();
        Runnable run2 = new Runnable() {
            
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("B第" + i2.incrementAndGet() + "次执行");
            }
        };
        
        final AtomicInteger i3 = new AtomicInteger();
        Runnable run3 = new Runnable() {
            
            @Override
            public void run() {
                System.out.println("C第" + i3.incrementAndGet() + "次执行");
            }
        };
        
        Callable<String> call1 = new Callable<String>() {
            
            @Override
            public String call() throws Exception {
                return "当前B: " + i2.get();
            }
        };
        
        
        // 线程池在没有到达最大线程数量时会优先创建新的线程来执行而不是使用空闲线程(eg:如果只有一个定时任务。一个线程执行1s,周期为2s,那么会在0,2,4...分别创建一个新线程,即使之前的线程有空闲的)
        // ps:这个是我根据现象做的猜测-定时任务的条件达成(本次队列执行开始或者本次队列执行完毕)之后并不是寻求新线程去进行运行,而是将其加入其维护的自身内部类(队列DelayedWorkQueue)里面。然后线程会从这个队列里面取出过期元素执行。
        //                    不过并不是和DelayQueue的阻塞取出方法一样如果第一个不过期会阻塞后面的过期的。他用peek取出元素并判断是否过期,直到找到第一个过期元素,实现了非阻塞且先进先过期元素先出的情况。
        ScheduledThreadPoolExecutor.scheduleAtFixedRate(run1, 0, 1, TimeUnit.SECONDS);  // 周期性的执行Runable(延迟时间以上一个任务开始时间开始计算eg:一个线程执行1s,周期为2s,那么它会在0,2,4,6...执行  一个线程执行4s,周期为2s,那么它会在0,4,8,12...执行)
//        ScheduledThreadPoolExecutor.scheduleAtFixedRate(run2, 0, 1, TimeUnit.SECONDS);
        ScheduledThreadPoolExecutor.scheduleWithFixedDelay(run2, 0, 5, TimeUnit.SECONDS);   // 周期性的执行Runable(延迟时间以上一个任务结束时间开始算。eg:一个线程执行1s,周期为2s,那么它会在0,3,6,9...执行)
        ScheduledThreadPoolExecutor.schedule(run3, 20, TimeUnit.SECONDS);    // 延迟指定时间执行Runable
        ScheduledFuture f = ScheduledThreadPoolExecutor.schedule(call1, 1, TimeUnit.SECONDS);   // 延迟指定时间执行Callable并返回ScheduleFuture
        ScheduledThreadPoolExecutor.getContinueExistingPeriodicTasksAfterShutdownPolicy(); // 默认false(true:继续,false:放弃)
        ScheduledThreadPoolExecutor.setContinueExistingPeriodicTasksAfterShutdownPolicy(true);  // 线程池关闭之后定时任务是否继续执行,包括scheduleAtFixedRate和scheduleWithFixedDelay。如果有周期任务线程池关闭之后会保持最大线程数(如果关闭时线程还未到达最大线程数依然会建立新线程)。
        ScheduledThreadPoolExecutor.getExecuteExistingDelayedTasksAfterShutdownPolicy();    // 默认true(true:继续,false:放弃)
        ScheduledThreadPoolExecutor.setExecuteExistingDelayedTasksAfterShutdownPolicy(true);    // 线程池关闭之后是否继续执行delay任务,如果只有延迟任务线程池关闭之后且这个延时任务执行后会销毁所有线程
        ScheduledThreadPoolExecutor.getRemoveOnCancelPolicy(); // 默认为false
        ScheduledThreadPoolExecutor.setRemoveOnCancelPolicy(true);  // 设置是否在任务被取消之后立刻从队列中移出
        try {
            System.out.println(f.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        try {
            Thread.sleep(10000);
            ScheduledThreadPoolExecutor.shutdown();
            System.out.println("shutdown end");
            Thread.sleep(20000);
            ScheduledThreadPoolExecutor.execute(run3);// shutdown之后再提交任务就会被拒绝(执行定义的拒绝策略)(也就是说setContinueExistingPeriodicTasksAfterShutdownPolicy和setExecuteExistingDelayedTasksAfterShutdownPolicy只负责线程关闭之前的任务)
        } catch (InterruptedException e) {
            System.out.println(1);
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } 
        
        System.out.println("isShutdown:" + ScheduledThreadPoolExecutor.isShutdown());
    }
}

发布了29 篇原创文章 · 获赞 11 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/yue_hu/article/details/79909479