高并发编程之ScheduledThreadPoolExecutor讲解

高并发编程之ScheduledThreadPoolExecutor讲解一、ScheduledThreadPoolExecutor介绍ScheduledThreadPoolExecutor,它可另行安排在给定的延迟后运行命令,或者定期执行命令。需要多个辅助线程时,或者要求ThreadPoolExecutor具有额外的灵活性或功能时,此类要优于Timer。二、ScheduledThreadPoolExecutor相对于Timer的优势ScheduledThre…

一、ScheduledThreadPoolExecutor介绍
ScheduledThreadPoolExecutor,它可另行安排在给定的延迟后运行命令,或者定期执行命令。需要多个辅助线程时,或者要求 ThreadPoolExecutor 具有额外的灵活性或功能时,此类要优于Timer。

二、ScheduledThreadPoolExecutor相对于Timer的优势
ScheduledThreadPoolExecutor是一个使用线程池执行定时任务的类,相较于Java中提供的另一个执行定时任务的类Timer,其主要有如下两个优点:
①、使用多线程执行任务,不用担心任务执行时间过长而导致任务相互阻塞的情况,Timer是单线程执行的,因而会出现这个问题;
②、不用担心任务执行过程中,如果线程失活,其会新建线程执行任务,Timer类的单线程挂掉之后是不会重新创建线程执行后续任务的。

除去上述两个优点外,ScheduledThreadPoolExecutor还提供了非常灵活的API,用于执行任务。其任务的执行策略主要分为两大类:

①在一定延迟之后只执行一次某个任务:
1、schedule(Callable callable, long delay, TimeUnit unit)
创建并执行在给定延迟后启用的 ScheduledFuture。
2、schedule(Runnable command, long delay, TimeUnit unit)
创建并执行在给定延迟后启用的一次性操作。

②在一定延迟之后周期性的执行某个任务:
1、scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;也就是将在 initialDelay 后开始执行,然后在 initialDelay+period 后执行,接着在 initialDelay + 2 * period 后执行,依此类推。
2、scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟。

三、Java代码示例
①、schedule(Runnable command, long delay, TimeUnit unit) :创建并执行在给定延迟后启用的一次性操作。

package ThreadPool;

import java.sql.Time;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author czd
 */
public class ScheduledThreadPoolExecutorTest {
    public static void main(String[] args) {
        ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(2);
       //1、schedule(Runnable command, long delay, TimeUnit unit)
        ScheduledFuture future = scheduledThreadPoolExecutor.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("当前时间:" + System.currentTimeMillis());
            }
        }, 2 ,TimeUnit.SECONDS);

		//有兴趣可以把下面两行代码的注释去掉玩玩看
        //cancel(true):是取消延迟执行
//        future.cancel(true);

    }
}

输出结果
在这里插入图片描述
②、scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;也就是将在 initialDelay 后开始执行,然后在 initialDelay+period 后执行,接着在 initialDelay + 2 * period 后执行,依此类推。

package ThreadPool;

import java.sql.Time;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author czd
 */
public class ScheduledThreadPoolExecutorTest {
    public static void main(String[] args) {
        ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(2);
        //2、scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
        scheduledThreadPoolExecutor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("当前时间:" + System.currentTimeMillis() + " 我是周期性执行!");
            }
        }, 2 , 5,TimeUnit.SECONDS);

    }
}

输出结果
在这里插入图片描述
scheduleAtFixedRate总结:
1、当执行时间 > 频率时间时 在程序结束本次执行后,会立即进行下一次的执行。
2、当执行时间 < 频率时间时 在程序结束本次执行后,会等到频率时间到了再去执行下一次。

③、scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟。

package ThreadPool;

import java.sql.Time;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author czd
 */
public class ScheduledThreadPoolExecutorTest {
    public static void main(String[] args) {
        ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(2);
        //3、scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
        scheduledThreadPoolExecutor.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                System.out.println("当前时间:" + System.currentTimeMillis() + " 我是周期性执行!");
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, 2 , 5,TimeUnit.SECONDS);
    }
}

输出结果
在这里插入图片描述
scheduleWithFixedDelay总结:
程序确实是在上一次执行完毕之后5s钟再次执行 也就是说 scheduleWithFixedDelay 是在上一次线程执行结束之后的多长时间执行(在这个示例就是一共2+5执行)。

四、ScheduledThreadPoolExecutor中的线程A执行某个周期任务分为4个步骤;
①、线程A从DelayQueue中获取已经到期的ScheduledFutureTask(DelayQueue.take())。
②、执行这个任务。
③、修改这个任务的time变量为下次将要执行的时间;
④ 把该任务放回DelayQueue中(DelayQueue.add())。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/35007.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注