Android 的 Timer 和 TimerTask

在这里插入图片描述

Timer 简介(来自Gemini)

Timer 是 Java 中用于创建定时任务的类。它位于 java.util 包中。可以使用 Timer 来安排一次性或定期执行的任务。
每个 Timer 对象都对应一个后台线程。此线程负责从任务队列中检索任务并按计划执行它们。

使用 Timer

要使用 Timer,首先需要创建一个 Timer 对象。然后,可以使用该对象的 schedule() 方法来安排任务。

schedule() 方法有三个参数:

  • task: 要执行的任务
  • delay: 任务延迟时间(以毫秒为单位)
  • period: 任务的执行周期(以毫秒为单位)

如果 period 为 0,则任务将只执行一次。如果 period 大于 0,则任务将定期重复执行。

以下是一个示例,说明如何使用 Timer 来创建一个每隔 1 秒打印“Hello, world!”消息的任务:

Timer timer = new Timer();
TimerTask task = new TimerTask() {
    @Override
    public void run() {
        System.out.println("Hello, world!");
    }
};

timer.schedule(task, 0, 1000);

Timer 和 TimerTask

TimerTask 是一个抽象类,用于表示要由 Timer 执行的任务。TimerTaskrun() 方法将包含要执行的任务的代码。

以下是一个示例 TimerTask 类,用于在 5 秒后打印“Hello, world!”消息:

class MyTimerTask extends TimerTask {
    @Override
    public void run() {
        System.out.println("Hello, world!");
    }
}

要使用 TimerTask 类,首先需要创建一个该类的子类。然后,可以将该子类的对象传递给 Timer 的 schedule() 方法。

取消 Timer 任务

可以使用 Timer 的 cancel() 方法来取消任务。

以下是一个示例,说明如何取消上例中的任务:

Java

timer.cancel();

注意事项

  • Timer 任务是在后台线程中执行的。这意味着它们不应执行任何可能阻塞 UI 线程的操作。
  • Timer 任务不应该长时间运行。如果需要执行长时间运行的任务,则应使用其他方法,例如 HandlerThread。

替代方案

除了 Timer 之外,Android 还提供了一些其他用于创建定时任务的类和方法。这些包括:

  • AlarmManager: 用于设置一次性或定期警报
  • Handler: 用于在主线程或后台线程中排队执行任务
  • JobScheduler: 用于安排在设备空闲时执行的作业

何时使用 Timer

Timer 适用于需要在后台执行简单任务的情况。例如,可以使用 Timer 来创建每隔几秒刷新一次屏幕的任务或每隔几分钟将数据同步到服务器的任务。

但是,如果需要执行更复杂的任务或需要确保任务在特定时间执行,则应使用其他方法。


Timer在cancel后不可以重复调用

在timer调用了cancel后, 再次schedule报错:

Process: com.android.sdktest, PID: 9264
java.lang.IllegalStateException: Timer already cancelled.
	at java.util.Timer.sched(Timer.java:404)
	at java.util.Timer.schedule(Timer.java:255)
	at com.android.sdktester.cases.TimerTester.start(TimerTester.java:24)
	at com.android.sdktester.MainActivity.onClick(MainActivity.java:23)
	at android.view.View.performClick(View.java:7322)
	at android.view.View.performClickInternal(View.java:7296)
	at android.view.View.access$3600(View.java:839)
	at android.view.View$PerformClick.run(View.java:28319)
	at android.os.Handler.handleCallback(Handler.java:900)
	at android.os.Handler.dispatchMessage(Handler.java:103)
	at android.os.Looper.loop(Looper.java:219)
	at android.app.ActivityThread.main(ActivityThread.java:8673)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1109)

在 Android 中,Timer 类用于创建定时任务。Timer 的 cancel() 方法可以取消所有已安排的任务并停止 Timer 线程。一旦 Timer 线程被取消,就不能再重新启动。

Timer 线程是一个后台线程。当 Timer 任务被取消时,Timer 线程将被终止。这意味着 Timer 线程不再能够执行任何新的任务。

如果尝试在取消 Timer 线程后重新启动它,则会抛出 **IllegalStateException** 异常。

解决这个问题需要创建一个新的 Timer 对象并使用新的 schedule() 方法安排新的任务。

TimerTask 也不可以重复使用

TimerTask 类用于表示要由 Timer 执行的任务。TimerTask 的 run() 方法将包含要执行的任务的代码。

原因

TimerTask 类不是线程安全的。这意味着如果同一个 TimerTask 对象被多个 Timer 任务使用,则可能导致数据竞争和其他问题。

Timer.java

    private void sched(TimerTask task, long time, long period) {
        if (time < 0)
            throw new IllegalArgumentException("Illegal execution time.");

        // Constrain value of period sufficiently to prevent numeric
        // overflow while still being effectively infinitely large.
        if (Math.abs(period) > (Long.MAX_VALUE >> 1))
            period >>= 1;

        synchronized(queue) {
            if (!thread.newTasksMayBeScheduled)
                throw new IllegalStateException("Timer already cancelled.");

            synchronized(task.lock) {
                **if (task.state != TimerTask.VIRGIN)**
                    throw new IllegalStateException(
                        "Task already scheduled or cancelled");
                task.nextExecutionTime = time;
                task.period = period;
                task.state = TimerTask.SCHEDULED;
            }

            queue.add(task);
            if (queue.getMin() == task)
                queue.notify();
        }
    }

TimerTask.java

    public boolean cancel() {
        synchronized(lock) {
            boolean result = (state == SCHEDULED);
            state = CANCELLED;
            return result;
        }
    }

为了避免这些问题,应为每个 Timer 任务创建一个新的 TimerTask 对象


一个 Timer 可以同时计划多个 TimerTask。

Timer 类用于创建定时任务。Timer 的 schedule() 方法可以安排一个或多个任务。

以下是一个示例,说明如何使用 schedule() 方法安排多个任务:

Timer timer = new Timer();

TimerTask task1 = new TimerTask() {
    @Override
    public void run() {
        System.out.println("Task 1");
    }
};

TimerTask task2 = new TimerTask() {
    @Override
    public void run() {
        System.out.println("Task 2");
    }
};

timer.schedule(task1, 0, 1000);
timer.schedule(task2, 500, 1000);

在这个示例中,task1 将在 0 毫秒后立即执行,然后每隔 1 秒重复执行一次。task2 将在 500 毫秒后执行,然后每隔 1 秒重复执行一次。

Timer 如何管理多个任务

Timer 使用一个队列来存储已安排的任务。Timer 线程负责从队列中检索任务并按计划执行它们。

当 Timer 任务被安排时,它将被添加到队列的末尾。Timer 线程将从队列的头部检索任务。这意味着最先安排的任务将首先执行。

如果有多个任务在同一时间就绪,则 Timer 线程将按 FIFO(先进先出)的顺序执行它们。

注意事项

  • Timer 任务是在后台线程中执行的。这意味着它们不应执行任何可能阻塞 UI 线程的操作。
  • Timer 任务不应该长时间运行。如果需要执行长时间运行的任务,则应使用其他方法,例如 HandlerThread。

只要Timer不cancel, 可以反复计划新的任务

Timer timer = new Timer();
TimerTask t1, t2, t3;
//省略创建TimerTask代码....
{
	timer.schedule(t1, 0, 1000);
	timer.schedule(t2, 0, 1000;
	
	Thread.sleep(10 * 1000);//等待10秒
	t1.cancel();
	t2.cancel();
	
	Thread.sleep(5000);
	timer.schedule(t3, 0, 1000;
	
	Thread.sleep(5000);
	t3.cancel();
}
timer.cancel()

这段代码使用了 Thread.sleep() 方法来控制任务的执行顺序。在 Thread.sleep() 方法执行期间,Timer 线程无法从任务队列中检索任务,因此即使 t1t2 任务已经被取消,它们也不会再被执行。使用了 t1.cancel()t2.cancel() 方法来显式地将 t1t2 任务从 Timer 的任务队列中删除。这可以确保这两个任务不会再次被执行.

参考

Timer定时器_的技术博客

Android 定时器Timer的使用

Android 开发Timer与TimerTask - 观心静

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/608453.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

3D 渲染至少需要多少显存?显存真得越大越好吗?

无论是电影制作、游戏开发还是建筑效果图设计&#xff0c;在今天的计算机图形学领域&#xff0c;都需要强大的图形处理能力。而显存&#xff08;VRAM&#xff09;作为支持这一切的重要组成部分&#xff0c;对于高效3D渲染同样至关重要。在本文中&#xff0c;我们将一起探讨显存…

Cmake-learning

可以把cmake看成一款自动生成 Makefile的工具&#xff0c;所以编译流程就变成了&#xff1a;cmake—>make–>可执行文件 在哪个目录执行cmake txt位置 就会在哪个目录生成构造文件和可执行文件 project(HELLO): 非强制&#xff0c;指明项目名称 add_executable(he…

【算法】滑动窗口——水果成篮

本篇博客是我对“水果成篮”这道题由暴力解法到滑动窗口思路的具体思路&#xff0c;有需要借鉴即可。 目录 1.题目2.暴力求解3.暴力优化3.1每次right不用回退3.2有些left长度一定不如前一个&#xff0c;不用走&#xff0c;left不回退 4.滑动窗口算法5.总结 1.题目 题目链接&am…

怎么用AI软件设计字体

一 工具准备 软件&#xff1a;Adobe illustrator 如下网盘自取 链接&#xff1a;https://pan.baidu.com/s/1hlImpN4QlsSkOLLUxINOGA 提取码&#xff1a;love 安装的时候看不全界面&#xff0c;多按几下tab键就能看到按钮。 直接找一款喜欢的字体修改&#xff0c;字体包如下…

物联网网关制造生产全流程揭秘!

如果您正有开发和定制物联网网关的计划&#xff0c;找一个专业的物联网设备厂商协助您制造生产物联网网关可以节省大量时间和成本&#xff0c;可以让您能专注于当前核心业务&#xff0c;而无需将精力过多地投入到自己不擅长的领域。 当然&#xff0c;了解物联网网关的测试和制…

基于JSP动漫论坛的设计与实现(二)

目录 3. 系统开发环境及技术介绍 3.1 开发环境 3.2 开发工具 3.2.1 MyEclipse8.5 3.2.2 MySql 3.3 相关技术介绍 3.3.1 JSP技术简介 3.3.2 JDBC技术技术简介 3.3.3 MVC模式与Struts框架技术 4. 总体设计 4.1 系统模块总体设计 4.1.1 普通用户模块设计 4…

数据库的使用基础-SQL语句

一、在MYSQL中&#xff0c;创建数据库&#xff0c;语法如下&#xff1a; CREATE DATABASE [IF NOT EXISTS] <数据库名> [[DEFAULT] CHARACTER SET <字符集名>] [[DEFAULT] COLLATE <校对规则名>];[ ]中的内容是可选的。语法说明如下&#xff1a; <数据库…

LeetCode738:单调递增的数字

题目描述 当且仅当每个相邻位数上的数字 x 和 y 满足 x < y 时&#xff0c;我们称这个整数是单调递增的。 给定一个整数 n &#xff0c;返回 小于或等于 n 的最大数字&#xff0c;且数字呈 单调递增 。 332 代码 class Solution { public:int monotoneIncreasingDigits(…

Imagine Flash、StyleMamba 、FlexControl、Multi-Scene T2V、TexControl

本文首发于公众号&#xff1a;机器感知 Imagine Flash、StyleMamba 、FlexControl、Multi-Scene T2V、TexControl You Only Cache Once: Decoder-Decoder Architectures for Language Models We introduce a decoder-decoder architecture, YOCO, for large language models, …

QT---day4事件

1、思维导图 2、 头文件 #ifndef MYWIDGET_H #define MYWIDGET_H #include <QWidget> #include<QIcon> //图标类 #include<QLabel> //标签类 #include<QMovie> //动图类 #include<QLineEdit> //行编辑器类 #include<QPushButton> //按钮…

AJAX知识点(前后端交互技术)

原生AJAX AJAX全称为Asynchronous JavaScript And XML,就是异步的JS和XML&#xff0c;通过AJAX可以在浏览器中向服务器发送异步请求&#xff0c;最大的优势&#xff1a;无需刷新就可获取数据。 AJAX不是新的编程语言&#xff0c;而是一种将现有的标准组合在一起使用的新方式 …

【进程等待】阻塞等待 | options非阻塞等待

目录 waitpid 阻塞等待 options&非阻塞等待 pid_t返回值 阻塞等待VS非阻塞等待 waitpid 回顾上篇&#xff1a; pid_ t waitpid(pid_t pid, int *status, int options); 返回值&#xff1a; 当正常返回的时候waitpid返回收集到的子进程的进程ID&#xff1b;如果设置了…

C++容器之vector类

目录 1.vector的介绍及使用1.1vector的介绍1.2vector的使用1.2.1 vector的定义1.2.2 vector iterator 的使用1.2.3 vector 空间增长问题1.2.4 vector 增删查改1.2.5vector 迭代器失效问题1.2.6 vector 在OJ中的使用。 2.vector深度剖析及模拟实现2.1 std::vector的核心框架接口…

金三银四面试题(二十五):策略模式知多少?

什么是策略模式 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;旨在定义一系列算法&#xff0c;将每个算法封装到一个独立的类中&#xff0c;使它们可以互换。策略模式让算法的变化独立于使用它们的客户端&#xff0c;使得客户端可以根据…

车载测试系列:入行车载测试分享

车载测试前景如何&#xff1f; 软件定义汽车时代的发展趋势&#xff0c;随着控制器自主开发力度的加强&#xff0c;作为V流程中必备环节&#xff0c;车载测试工程师岗位需求会越来越多&#xff1b;控制器集成化&#xff0c;功能集成程度越来越高&#xff0c;对于测试工程师的知…

3. 初探MPI——(非阻塞)点对点通信

系列文章目录 初探MPI——MPI简介初探MPI——&#xff08;阻塞&#xff09;点对点通信初探MPI——&#xff08;非阻塞&#xff09;点对点通信初探MPI——集体通信 文章目录 系列文章目录前言一、Non-blocking communications1.1 Block version1.2 Non-blocking version 二、准…

思维导图软件哪个好?盘点这5款好用的工具!

思维导图作为一种有效的思维工具&#xff0c;在日常生活和工作中扮演着越来越重要的角色。无论是学习、工作规划&#xff0c;还是项目管理&#xff0c;思维导图都能帮助我们更好地组织思路&#xff0c;提升工作效率。然而&#xff0c;市面上众多的思维导图软件让人眼花缭乱&…

软件系统工程建设全套资料(交付清单)

软件全套精华资料包清单部分文件列表&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&#xff0c;产品需求规格说明书&#xff0c;需求调研计划&#xff0c;用户需求调查单&#xff0c;用户需求说明书&#xff0c;概要设计说明书&#xff0c…

C++类和对象(4)

目录 1.初始化列表 2.单参数里面的隐式类型转换 3.多参数的隐式类型转换 4.匿名对象 1.初始化列表 &#xff08;1&#xff09;首先看一下初始化列表具体是什么&#xff1f; 这个就是初始化列表的具体形式&#xff0c;对&#xff0c;你没有看错&#xff0c;这个初始化列表里…

python:画折线图

import pandas as pd import matplotlib.pyplot as plt from matplotlib.font_manager import FontProperties# 设置新宋体字体的路径 font_path D:/reportlab/simsun/simsun.ttf# 加载新宋体字体 prop FontProperties(fnamefont_path)""" # 读取 xlsx 文件 d…