Timer+TimerTask的升级版ScheduledExecutorService

一、ScheduledExecutorService是一个接口,是继承于接口ExecutorService的子类,而ExecutorService又是继承于Executor接口的子类。

二、这里我们先从继承的最终类Executor接说起。
Executor接口只有一个方法:void execute(Runnable command);他是一个同步方法,接收一个Runnable接口作为参数。具体由implements实现他的类来实现。

execute():一个同步方法;与之对应的是一步方法enqueue()。二者区别:

execute():同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回,处于等待状态直到得到该调用的结果。
          也就是必须一件一件事做,等前一件做完了才能做下一件事.
enqueue():异步,当一个异步过程调用发出后,他可以做其他的任务处理,不必等待调用结果。实际处理这个调用的部件在
          完成后,通过状态、通知和回调来通知调用者。简单说就是调用者可以同时处理很多事情,而不是一件接一件。

因此,Executor接口理解起来很简单,不用多说。

三、接下来我们继续说接口ExecutorService。这个接口稍微复杂一点。它包含一下四大系列的方法:

1、shutdown系列方法:

	void shutdown();作用:平滑的关闭ExecutorService,当此方法被调用时,ExecutorService停止接收新的任务并且等待已经提交的任务(包含提交正在执行和提交未执行)执行完成。当所有提交任务执行完毕,线程池即被关闭。
	List<Runnable> shutdownNow();作用:获取终止线程池中线程的执行的时候线程池中线程列表。
	boolean isShutdown();作用:判断线程是否已经停止执行

2、Terminate系列方法:

	boolean isTerminated();作用:确认线程是否已经停止执行
	boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;作用::接收人timeout和TimeUnit两个参数,用于设定超时时间及单位。当等待超过设定时间时,会监测ExecutorService是否已经关闭,若关闭则返回true,否则返回false。一般情况下会和shutdown方法组合使用。

简单来说就是:shutdown()用于关闭线程池,awaitTermination()用于确定线程池是否已经关闭。具体使用如下:

public class Task implements Callable{
    @Override
    public Object call() throws Exception {
        System.out.println("普通任务");
        return null;
    }
}

public class LongTask implements Callable{
    @Override
    public Object call() throws Exception {
        System.out.println("长时间任务");
        TimeUnit.SECONDS.sleep(5);
        return null;
    }
}

public class TestShutDown {
    public static void main(String[] args) throws InterruptedException{
        ScheduledExecutorService service = Executors.newScheduledThreadPool(4);
        service.submit(new Task());
        service.submit(new LongTask());
        service.submit(new Task());
		// 平滑的关闭ExecutorService
        service.shutdown();
        // 在1秒钟后监测ExecutorService是否已经关闭
       while (service.isShutdown() || service.isTerminated() || !service.awaitTermination(1, TimeUnit.SECONDS)){
        	System.out.println("线程池没有关闭");
		}
        System.out.println("线程池已经关闭");
    }
}

3、submit()系列方法:

submit(Callable<T> task);作用:接收一个实现了Callable接口的参数,使用方式如上面main()方法中。
submit(Runnable task, T result);作用:接收一个实现了Runnable 接口的参数以及一个泛型参数T,泛型参数可以为null,这时跟下面的这个方法相同。
submit(Runnable task);作用:接收一个实现了Runnable 接口的参;

submit()方法接收一个实现了Runnable 接口的参数的使用如下:

ScheduledExecutorService executorService04 = new ScheduledThreadPoolExecutor(3);
executorService04.submit(new Runnable() {
   @Override
   public void run() {
		// TODO:
   }
 });
或者:
executorService04.submit(new Runnable() {
    @Override
    public void run() {
        // TODO:
    }
}, null);

此二者的使用没什么大的不同,另外,从实现的功能上来看,他与前面的submit(Callable task)接收一个实现了Callable接口的参数方法一样,不同的用法而已。

4、invoke系列方法:

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;

上面这四个方法没有深入的研究和使用过,不知道其具体的作用,但从其命名( invoke:调用)来看,不难理解:

调用所有或者任意一个实现了Callable接口为对象的Collection集合为参数的方法。若有timeout参数,则是监控其运行超时。

invoke系列方法先就讲这么多,以后研究透了再来细说。

四、终于轮到ScheduledExecutorService了,他有4个方法:

// schedule方法调度的任务在delay时长的延迟后只执行一次。
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);

//根据前面的代码解说,我们可以推测:他其实和上面的schedule()方法一样
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);

 // scheduleAtFixedRate:该方法在initialDelay时长后第一次执行任务,以后每隔period时长,再次执行任务。注意,period是从任务开始执行算起的。开始执行任务后,定时器每隔period时长检查该任务是否完成,如果完成则再次启动任务,否则等该任务结束后才再次启动任务。
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);

// 该方法在initialDelay时长后第一次执行任务,以后每当任务执行完成后,等待delay时长,再次执行任务。
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);

贴上使用代码及运行结果:

ScheduledExecutorService executorService00;
ScheduledExecutorService executorService01;
ScheduledExecutorService executorService02;
ScheduledExecutorService executorService03;
ScheduledExecutorService executorService04;
ScheduledExecutorService executorService05;
ScheduledExecutorService executorService06;

private void scheduledTimer() throws InterruptedException {
    executorService00 = new ScheduledThreadPoolExecutor(2);
    executorService00.schedule(new Callable<Object>() {
        @Override
        public Object call() throws Exception {
            Log.i(TAG, "ScheduledExecutorService00 \n ScheduledThreadPoolExecutor的schedule方法接收一个Callable对象作为参数");
            return null;
        }
    }, 1, TimeUnit.SECONDS);

    executorService01 = new ScheduledThreadPoolExecutor(2);
    // schedule方法调度的任务在delay时长的延迟后只执行一次。
    executorService01.schedule(runnable01, 3, TimeUnit.SECONDS);

    executorService02 = new ScheduledThreadPoolExecutor(2);
    // scheduleAtFixedRate:该方法在initialDelay时长后第一次执行任务,以后每隔period时长,再次执行任务。
    // 注意,period是从任务开始执行算起的。开始执行任务后,定时器每隔period时长检查该任务是否完成,
    // 如果完成则再次启动任务,否则等该任务结束后才再次启动任务。
    executorService02.scheduleAtFixedRate(runnable02, 2, 2, TimeUnit.SECONDS);

    executorService03 = new ScheduledThreadPoolExecutor(2);
    // 该方法在initialDelay时长后第一次执行任务,以后每当任务执行完成后,等待delay时长,再次执行任务。
    executorService03.scheduleWithFixedDelay(runnable03, 1, 1, TimeUnit.SECONDS);

    executorService04 = new ScheduledThreadPoolExecutor(2);
    executorService04.execute(runnable04);

    executorService05 = new ScheduledThreadPoolExecutor(3);
    executorService05.submit(new Callable<Object>() {
        @Override
        public Object call() throws Exception {
            Log.i(TAG, "ScheduledExecutorService05 \n ScheduledThreadPoolExecutor实现了ScheduledExecutorService接口," +
                    "继承于ThreadPoolExecutor");
            return null;
        }
    });

    executorService06 = new ScheduledThreadPoolExecutor(3);
    executorService06.submit(new Runnable() {
        @Override
        public void run() {
            Log.i(TAG, "ScheduledExecutorrunnable06 \n ScheduledThreadPoolExecutor实现了ScheduledExecutorService接口," +
                    "继承于ThreadPoolExecutor");
        }
    });

    executorService03.shutdown();
    Log.i(TAG, "ScheduledExecutorscheduledTimer: isShutdown===" + executorService03.isShutdown());
    Log.i(TAG, "ScheduledExecutorTimer: isTerminated===" + executorService03.isTerminated());

    boolean awaitTermination = executorService03.awaitTermination(5, TimeUnit.SECONDS);
    Log.i(TAG, "ScheduledExecutorscheduledTimer: awaitTermination===" + awaitTermination);
    if (awaitTermination){
        Log.i(TAG, "ScheduledExecutorscheduledTimer: 线程池没有关闭===");
    }
}

Runnable runnable01 = new Runnable() {
    @Override
    public void run() {
        Log.i(TAG, "ScheduledExecutorrunnable01 \n ScheduledThreadPoolExecutor的schedule方法接收一个Runnable对象作为参数");
    }
};

Runnable runnable02 = new Runnable() {
    @Override
    public void run() {
        Log.i(TAG, "ScheduledExecutorrunnable02 \n ScheduledThreadPoolExecutor的schedule方法接收一个Runnable对象作为参数");
    }
};

Runnable runnable03 = new Runnable() {
    @Override
    public void run() {
        Log.i(TAG, "ScheduledExecutorrunnable03 \n ScheduledThreadPoolExecutor的schedule方法接收一个Runnable对象作为参数");
    }
};

Runnable runnable04 = new Runnable() {
    @Override
    public void run() {
        Log.i(TAG, "ScheduledExecutorrunnable04 \n ScheduledThreadPoolExecutor的schedule方法接收一个Runnable对象作为参数");
    }
};

运行结果如下:
在这里插入图片描述

好了,ScheduledExecutorService学习讲解完毕,下一篇,我们学习分析ScheduledThreadPoolExecutor

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值