ScheduledExecutorService 和 Timer 的区别

Timer的内部只有一个线程,如果有多个任务的话就会顺序执行,这样我们的延迟时间和循环时间就会出现问题。

ScheduledExecutorService是线程池,所以就不会出现这个情况,在对延迟任务和循环任务要求严格的时候,就需要考虑使用ScheduledExecutorService了。

ScheduledExecutorService有三种常用方法:

 // 通过静态方法创建ScheduledExecutorService的实例
    private ScheduledExecutorService mScheduledExecutorService = Executors.newScheduledThreadPool(4);
 //建议使用下面方法ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(4);
         // 延时任务
        mScheduledExecutorService.schedule(threadFactory.newThread(new Runnable() {
            @Override
            public void run() {
                Log.e("lzp", "first task");
            }
        }), 1, TimeUnit.SECONDS);

        // 循环任务,按照上一次任务的发起时间计算下一次任务的开始时间
        mScheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                Log.e("lzp", "first:" + System.currentTimeMillis() / 1000);
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, 1, 1, TimeUnit.SECONDS);

        // 循环任务,以上一次任务的结束时间计算下一次任务的开始时间
        mScheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                Log.e("lzp", "scheduleWithFixedDelay:" + System.currentTimeMillis() / 1000);
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, 1, 1, TimeUnit.SECONDS);

ScheduledExecutorService是延时执行的线程池,推荐用ScheduledExecutorService代替timer定时器。 创建一个ScheduledExecutorService很简单


ScheduledExecutorService service = Executors.newScheduledThreadPool(num);

延时n秒执行:

//延时n秒执行
service.schedule(Runnable, n, TimeUnit.SECONDS);
service.schedule(Callable, n, TimeUnit.SECONDS);

列子:

 public static void main(String[] args) {
        ScheduledExecutorService service = Executors.newScheduledThreadPool(3);
        System.out.println("开始任务");
        //延时3秒执行
        service.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行任务");
            }
        }, 3, TimeUnit.SECONDS);
    }

log:

12-25 16:46:12.700 30954-30954/lbx.myapplication I/System.out: 开始任务
12-25 16:46:15.710 30954-31120/lbx.myapplication I/System.out: 执行任务

看下log的时间,可以发现,Runnable里的代码是在3秒后执行的。

二、ScheduledExecutorService的循环执行功能

//循环执行任务,首先延时m秒执行,n秒循环一次
service.scheduleAtFixedRate(Runnable, m, n, TimeUnit.SECONDS);

列子:

    public static void main(String[] args) {
        ScheduledExecutorService service = Executors.newScheduledThreadPool(3);
        System.out.println("开始任务");
        //延时3秒执行,每1秒执行一次
        service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行任务");
            }
        }, 3, 1, TimeUnit.SECONDS);
    }

log:

12-25 16:49:56.000 7698-7698/lbx.myapplication I/System.out: 开始任务
12-25 16:49:59.000 7698-7847/lbx.myapplication I/System.out: 执行任务
12-25 16:50:00.000 7698-7847/lbx.myapplication I/System.out: 执行任务
12-25 16:50:01.000 7698-8406/lbx.myapplication I/System.out: 执行任务
12-25 16:50:02.000 7698-8406/lbx.myapplication I/System.out: 执行任务
12-25 16:50:03.000 7698-8406/lbx.myapplication I/System.out: 执行任务
12-25 16:50:04.000 7698-8406/lbx.myapplication I/System.out: 执行任务

可以发现,刚开始演示了三秒,后续每1秒执行了一次Runnable里的代码逻辑。

三、ScheduledThreadPoolExecutor的使用

ScheduledThreadPoolExecutor是ScheduledExecutorService的子类,

ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(num);

它有以下常用的方法:

//获取未完成的任务队列
executor.getQueue();
//移除任务队列中的任务  future = executor.scheduleAtFixedRate/scheduleWithFixedDelay
executor.remove((Runnable) future);
//取消任务队列中的schedule任务,但不会在队列中删除,即getQueue的数量不会减1,executor.setRemoveOnCancelPolicy(true)的时候减1
boolean cancel = future.cancel(true);
//schedule任务是否取消
future.isCancelled()
//延时的schedule在shutdown后,不会继续执行没到时间的任务,默认是true,会执行一次正在倒计时的任务再结束
executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
//延时的scheduleAtFixedRate/scheduleWithFixedDelay在shutdown后,不会继续执行没到时间的任务,默认是true,会执行一次正在倒计时的任务再结束
executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);

猜你喜欢

转载自blog.csdn.net/wangxueqing52/article/details/80099670