定时任务ScheduledThreadPoolExecutor的使用详解

前短时间需要用到一个定时器处理蓝牙设备接收的数据,并且需要处理的频率是很快的,这就需要一个稳定的定时器来保证数据的长久进行。ScheduledThreadPoolExecutor这个类就是个很好的选择。

正常情况下,定时器我们都是用Timer和TimerTask这两个类就能完成定时任务,并且设置延长时间和循环时间间隔。
ScheduledThreadPoolExecutor也能完成Timer一样的定时任务,并且时间间隔更加准确。

误差说明:

我在后台程序看看一下Timer执行程序是有可能延迟1、2毫秒,如果是1秒执行一次的任务,1分钟有可能延迟60毫秒,一小时延迟3600毫秒,相当于3秒,实际用户看不出什么区别。
但是,如果我的程序需要每40毫秒就执行一次任务,如果还是有1、2毫秒的误差,1秒钟就有25毫秒的误差,大概40秒就有1秒的误差,十几分钟就有十几秒的误差,这对UI显示来说是延迟非常严重的了。
而我用ScheduledThreadPoolExecutor来做40毫秒的间隔任务,一般十几分钟才有1秒多的误差,这个还是能接受的。
这也是我用ScheduledThreadPoolExecutor这个类的原因。

ScheduledThreadPoolExecutor的介绍

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

使用Timer和TimerTask存在一些缺陷:

1.Timer只创建了一个线程。当你的任务执行的时间超过设置的延时时间将会产生一些问题。

2.Timer创建的线程没有处理异常,因此一旦抛出非受检异常,该线程会立即终止。

JDK 5.0以后推荐使用ScheduledThreadPoolExecutor。该类属于Executor Framework,它除了能处理异常外,还可以创建多个线程解决上面的问题

Timer和TimerTask的使用

这个大家应该都是会使用的了,但是还是給给大家看看代码:

        Timer  timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                log.e("time:");
        }, 2000, 40);//2000表示第一次执行任务延迟时间,40表示以后每隔多长时间执行一次run里面的任务

ScheduledThreadPoolExecutor的使用

这里先学会简单使用再深入探讨。

        ScheduledThreadPoolExecutor  scheduled = new ScheduledThreadPoolExecutor(2);
        scheduled.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                loge("time:");
        }, 0, 40, TimeUnit.MILLISECONDS);//0表示首次执行任务的延迟时间,40表示每次执行任务的间隔时间,TimeUnit.MILLISECONDS执行的时间间隔数值单位

间隔单位毫秒:TimeUnit.MILLISECONDS
间隔单位秒:TimeUnit.SECONDS
间隔单位分钟:TimeUnit.MINUTES
间隔单位小时:TimeUnit.HOURS
间隔单位天:TimeUnit.DAYS

定时器的一个实例

使用Timer和TimerTask、ScheduledThreadPoolExecutor显示秒的定时器

这里看起来是每秒刷新一次UI,但是我为了看40毫秒的延迟效果,是每40 毫秒index加一,添加25次后,刷新一次UI,表面上看起来是和每秒刷新的效果。

package com.example.wenzhi.scheduledthreadpoolexecutordemo;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class MainActivity extends AppCompatActivity {
    TextView tv_time;
    int      time;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_time = (TextView) findViewById(R.id.tv_time);
    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (time % 25 == 0) {
                tv_time.setText("" + time / 25);
     * 普通定时器
    Timer timer;
    public void timer(View view) {
        stopTimer1();
        timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                loge("time:" + time++);//add
                handler.sendEmptyMessage(11);
        }, 2000, 40);
    public void stop(View view) {
        stopTimer1();
     * 停止定时器
    private void stopTimer1() {
        if (timer != null) {
            timer.cancel();
            timer = null;
     * 稳定的定时器
    ScheduledThreadPoolExecutor scheduled;
    public void timer2(View view) {
        stopTimer2();
        scheduled = new ScheduledThreadPoolExecutor(2);
        scheduled.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                loge("time:" + time++);
                handler.sendEmptyMessage(11);
        }, 0, 40, TimeUnit.MILLISECONDS);
    public void stop2(View view) {
        stopTimer2();
     * 停止定时器
    private void stopTimer2() {
        if (scheduled != null) {
            scheduled.shutdownNow();
            scheduled = null;
    private void loge(String msg) {
        Log.e("TAG", msg);
    @Override
    protected void onDestroy() {
        super.onDestroy();
        System.exit(0);
     * 数据清零
    public void clear(View view) {
        time = 0;
        tv_time.setText("" + time);
11-29 01:08:09.940 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:0
11-29 01:08:09.980 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:1
11-29 01:08:10.020 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:2
11-29 01:08:10.060 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:3
11-29 01:08:10.100 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:4
11-29 01:08:10.140 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:5
11-29 01:08:10.180 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:6
11-29 01:08:10.224 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:7
11-29 01:08:10.264 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:8
11-29 01:08:10.304 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:9
11-29 01:08:10.344 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:10
11-29 01:08:10.384 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:11
11-29 01:08:10.424 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:12
11-29 01:08:10.468 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:13
11-29 01:08:10.508 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:14
11-29 01:08:10.548 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:15
11-29 01:08:10.592 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:16
11-29 01:08:10.632 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:17
11-29 01




    
:08:10.672 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:18
11-29 01:08:10.712 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:19
11-29 01:08:10.752 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:20

可以看到上面时间间隔不是很稳定,有几个是间隔40多毫秒的

ScheduledThreadPoolExecutor定时器

11-29 01:11:13.492 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:0
11-29 01:11:13.528 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:1
11-29 01:11:13.564 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:2
11-29 01:11:13.604 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:3
11-29 01:11:13.644 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:4
11-29 01:11:13.684 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:5
11-29 01:11:13.724 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:6
11-29 01:11:13.764 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:7
11-29 01:11:13.804 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:8
11-29 01:11:13.844 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:9
11-29 01:11:13.888 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:10
11-29 01:11:13.924 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:11
11-29 01:11:13.984 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:12
11-29 01:11:14.004 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:13
11-29 01:11:14.044 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:14
11-29 01:11:14.084 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:15
11-29 01:11:14.124 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:16
11-29 01:11:14.164 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:17
11-29 01:11:14.204 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:18
11-29 01:11:14.244 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:19
11-29 01:11:14.284 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:20

可以看到上面的数据除了第一个和第二个,其他的数据都是非常稳定的,间隔时间都是40毫秒。

而且时间越长越能看出,这两种定时器的差距。

共勉:当你的野心支撑不了你的梦想的时候,该努力了

转载请标明出处:【顾林海的博客】前言ScheduledThreadPoolExecutor继承自ThreadPoolExecutor,而ThreadPoolExecutor是线程池的核心实现类,用来执... 来自: 顾林海 ScheduledThreadPoolExecutor是ThreadPoolExecutor的子类;JDK api里是这么说的: ThreadPoolExecutor,它可另行安排在给定的延迟后运行命... 来自: weixin_33928137的博客 ScheduledThreadPoolExecutor是ThreadPoolExecutor的子类;JDK api里是这么说的:ThreadPoolExecutor,它可另行安排在给定的延迟后运行命令... 来自: 幻年,时光。 ScheduledThreadPoolExecutor是jdk提供的基础线程池之一。具有定时执行任务的功能。jgk中另外两种具有定时功能的线程池SingleThreadScheduledExecuto... 来自: yue_hu的博客 【文章后台管理系统】URL设计与建模分析+项目源码+运行界面栏目管理、文章列表、用户管理、角色管理、权限管理模块(文章最后附有源码)1. 这是一个什么系统?1.1 学习后台管理系统的原因随着时代的变迁... 来自: 程序媛乐园 ScheduledThreadPoolExecutor类并不是什么新出的功能了,在JDK1.5的时候就已经加入进来,开发他的正式并发大神Doug Lea。大概三四年前有整体学习过Java并发的源码。这... 定时任务就是在指定时间执行程序,或周期性执行计划任务。Java中实现定时任务的方法有很多,本文从从JDK自带的一些方法来实现定时任务的需求。Timer和TimerTask本文先介绍Java最原始的解决... 来自: BAT的乌托邦 前言同步I/O模型通常用于实现Reactor模式 异步I/O模型则用于实现Proactor模式 最后我们会使用同步I/O方式模拟出Proactor模式一、Reactor模式Reactor模式特点它要求... 来自: 江南、董少 点击上面↑「爱开发」关注我们每晚10点,捕获技术思考和创业资源洞察什么是ThreadLocalThreadLocal是一个本地线程副本变量工具类,各个线程都拥有一份线程私...... 来自: 爱开发 http://bbs.csdn.net/topics/380145101http://olylakers.iteye.com/blog/1218243http://zhidao.baidu.com/l...   定时任务就是在指定时间执行程序,或周期性执行计划任务。Java中实现定时任务的方法有很多,本文从从JDK自带的一些方法来实现定时任务的需求。一、Timer和TimerTask  Timer和Tim... 来自: weixin_33866037的博客 ​ 进程通信是指进程之间的信息交换。这里需要和进程同步做一下区分,进程同步控制多个进程按一定顺序执行,进程通信是一种手段,而进程同步是目标。从某方面来讲,进程通信可以解决进程同步问题。​ 首先回顾下我... 来自: 丹丹的后花园 当时买mac的初衷,只是想要个固态硬盘的笔记本,用来运行一些复杂的扑克软件。而看了当时所有的SSD笔记本后,最终决定,还是买个好(xiong)看(da)的。已经有好几个朋友问我mba怎么样了,所以今天... 来自: Diana5253的博客 一、前言在可视化化程序设计的今天,借助于集成开发环境可以很快地生成程序,程序设计不再是计算机专业人员的专利。很多人认为,只要掌握几种开发工具就可以成为编程高手,其实,这是一种误解。要想成为一个专业的开... 来自: 牧小农 转自:https://segmentfault.com/a/1190000008038848在现实世界里,我们总是免不了要定期去做一件事情(比如上课)—— 在计算机的世界里,更是如此。比如我们手机每天... 来自: weixin_34204722的博客 研发效能提升是最近比较热门的一个话题,本人根据这几年的工作心得,做了一些思考总结,由于个人深度有限,暂且抛转引入。 三要素 任何生产力的提升都离不开这三个因素:人、流程和工具,少了其中任何一个因素都... 来自: 黄河敏捷开发 ScheduledThreadPoolExecutor继承自ThreadPoolExecutor。它主要用来在给定的延迟之后运 行任务,或者定期执行任务。ScheduledThreadPoolExec... 来自: 田野中的锋芒 如今,双11不光是购物狂欢节,更是对技术的一次“大考”,对于阿里巴巴企业内部运营的基础保障技术而言,亦是如此。回溯双11历史,这背后也经历过“小米加步枪”的阶段:作战室从随处是网线,交换机放地上的“一... 来自: 阿里云技术 在阿里,40岁的奋斗姿势在阿里,什么样的年纪可以称为老呢?35岁?在云网络,有这样一群人,他们的平均年龄接近40,却刚刚开辟职业生涯的第二战场。他们的奋斗姿势是什么样的呢?洛神赋“翩若惊鸿,婉若游龙。... 来自: 阿里云云栖号 从线程池的UML类图可以看到,ScheduledThreadPoolExecutor是ThreadPoolExecutor的子类,所以它拥有ThreadPoolExecutor的所有功能,同时它又实现... 来自: 余生爱静 点击蓝色“Creator星球游戏开发社区”关注我哟加个“星标”,一起快乐成长二哥,你好,我想知道一般程序猿都如何接私活,我也想接,能告诉我一些方法吗?上面是一个读者“烦不烦”问我的一个问题。其实不止是... 来自: 奎特尔星球 作者 |胡书敏责编 | 刘静出品 | CSDN(ID:CSDNnews)本人目前在一家知名外企担任架构师,而且最近八年来,在多家外企和互联网公司担任Java技术面试官,前后累计面试了有两三百位候选人。... 来自: CSDN资讯 一、准备工作u盘,电脑一台,win10原版镜像(msdn官网)二、下载wepe工具箱极力推荐微pe(微pe官方下载)下载64位的win10 pe,使用工具箱制作启动U盘打开软件,选择安装到U盘(按照操... 来自: weixin_41964258的博客 由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不知道要怎么回答你,主要取决于你想学习到哪些程度,不过针对这个问题,... 来自: 帅地 java自带的定时任务执行器为ScheduledThreadPoolExecutor,继承于线程池管理器ThreadPoolExecutor,常用方法如下,程序将每2秒输出一次系统时间。Schedul... 来自: 祈雨v的博客 导语:腾讯计费是孵化于支撑腾讯内部业务千亿级营收的互联网计费平台,在如此庞大的业务体量下,腾讯计费要支撑业务的快速增长,同时还要保证每笔交易不错账。采用最终一致性或离线补...... 来自: 腾讯技术工程 一、ScheduledThreadPoolExecutor简介1.1、构造方法ScheduledThreadPoolExecutor有四个构造方法,如下所示:ScheduledThreadPoolEx... 来自: freak_csh的博客 一、简介ScheduledThreadPoolExecutor是ThreadPoolExecutor的子类,继承了父类对线程的管理维护功能,通过还可以执行延迟和定时任务。/* * This c... 来自: 翻身已碰头的博客 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis原本是apache的一个开源项目iBatis, 2010年该项目由apache software fo... 来自: 谷哥的小弟 很早就很想写这个,今天终于写完了。游戏截图:编译环境: VS2017游戏需要一些图片,如果有想要的或者对游戏有什么看法的可以加我的QQ 2985486630 讨论,如果暂时没有回应,可以在博客下方留言... 来自: 张宜强的博客 Java提供Timer和ScheduledThreadPoolExecutor两个类实现定时任务,其中Timer简单易用,但所有任务都是由同一个线程来调度,任务串行执行,任务之间存在互相干扰,一是前一... 来自: weixin_33966365的博客     ScheduledThreadPoolExecutor除了具有ThreadPoolExecutor的所有功能外,还可以延迟执行任务或者周期性的执行某个任务。scheduleWithFixedD... 来自: olylakers的博客 前面我们已经学习了使用ThreadPoolExecutor类来实现自动创建和运行线程。但是那些线程都是一提交就会运行,我们有时候希望不要一提交就运行,而是延迟一段时间或者周期性的运行某个任务,这样我们... 来自: iteye_2022的博客 点击上方“程序员小明”,选择“星标”今晚可以不加班!网络上虽然已经有了很多关于程序员的话题,但大部分人对这个群体还是很陌生。我们在谈论程序员的时候,究竟该聊些什么呢?各位...... 来自: 程序员小明 ScheduledThreadPoolExecutor解析一(调度任务,任务队列):[url]http://donald-draper.iteye.com/blog/2367332[/url]Sche... 来自: Donald_Draper wenzhi20102321:xml2axml.jar工具: https://download.csdn.net/download/wenzhi20102321/12118311

javaj经典程序编程50题 qq_36450673:[reply]qq_42770224[/reply]内循环没有判断到sqrt(i)