Java并发基础02. 传统线程技术中的定时器技术
传统线程技术中有个定时器,定时器的类是Timer,我们使用定时器的目的就是给它安排任务,让它在指定的时间完成任务。所以先来看一下Timer类中的方法(主要看常用的TimerTask()
方法):
前面两个是在指定延迟后执行或者重复执行,后面两个是在指定时间执行或者重复执行。我们以前两个为例来研究一下定时器的使用。
先写一个简单的使用定时器的demo,然后慢慢引申。
public class TraditionalTimer {
public static void main(String[] args) {
//简单定时器的demo
new Timer().schedule(new TimerTask() {
@Override
public void run() {
//实际中会扔一个对象进来,我们就可以在这里操作这个对象的所有方法了
System.out.println("--boom--");//爆炸
}
}, 2000,3000);
//打印秒钟,一秒输出一次,用来方便观察的
while(true) {
System.out.println(new Date().getSeconds());
try {
Thread.sleep(1000);
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
我们用匿名内部类来定义了一个TimerTask对象,需要重写run()方法,然后运行这个程序,可以看出来第一次2秒钟后打印“--boom--,后面每隔3秒打印一次。
我们也可以自己来实现上面这个重复执行,我们用定时器的“连环套”!也就是定时器中再套定时器,一个定时器任务执行完了,在任务的最后再装一个定时器。那么我们需要先定义一个自己的定时器任务,在自己的定时器任务中再装一个定时器,把自定义的定时器任务扔进去。然后我们开启定时器的时候把自己定义的定时器任务扔进去即可。如下:
public class TraditionalTimer {
public static void main(String[] args) {
//自定义一个定时器任务
class MyTimerTask extends TimerTask {
@Override
public void run() {
System.out.println("--boom--");
//任务执行完再装一个定时器,扔进自定义的定时器任务
new Timer().schedule(new MyTimerTask(), 3000);
}
}
new Timer().schedule(new MyTimerTask(), 2000);//外面开启定时器
while(true) {//打印秒钟,一秒输出一次
System.out.println(new Date().getSeconds());
try {
Thread.sleep(1000);
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
这样的话,我们通过定时器的“连环套”很轻松的实现了连环爆炸。但是现在问题来了,上面提供的方法中重复执行都是每隔固定的时间,如果我想要隔2秒执行一次,再隔4秒执行一次,再隔2秒执行一次,再隔4秒执行一次……这该如何实现呢?
可以这样,我们定义一个全局的私有成员变量来记录爆炸次数,奇数的时候隔2秒炸,偶数的次数的话隔4秒炸,或者反过来也行,修改如下:
public class TraditionalTimer {
private static int count = 0; //记录爆炸的次数
public static void main(String[] args) {
class MyTimerTask extends TimerTask {
@Override
public void run() {
count = (count + 1) % 2; //结果只有0和1
System.out.println("--boom--");
new Timer().schedule(new MyTimerTask(), 2000+2000*count);//根据count结果设定新的定时时间
}
}
new Timer().schedule(new MyTimerTask(), 2000);
while(true) {//打印秒钟,一秒输出一次
System.out.println(new Date().getSeconds());
try {
Thread.sleep(1000);
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
这样的话,我们就实现了自定义爆炸间隔了。上面这个是通过定义一个全局私有变量来实现,其实我们也可以这么干:不是要实现两个不同时间间隔的连环炸么?我可以定义两个定时器任务A和B,在A执行完开启定时器,把B任务装进去,B执行完开启定时器把A装进去,这样也可以。如下:
public class TraditionalTimer {
public static void main(String[] args) {
new Timer().schedule(new MyTimerTaskA(), 2000);//A和B随便开一个
while(true) {//打印秒钟,一秒输出一次
System.out.println(new Date().getSeconds());
try {
Thread.sleep(1000);
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
//自定义两个定时器任务类,继承TimerTask即可
class MyTimerTaskA extends TimerTask {
@Override
public void run() {
System.out.println("--boomA--");
new Timer().schedule(new MyTimerTaskB(), 4000);
}
}
class MyTimerTaskB extends TimerTask {
@Override
public void run() {
System.out.println("--boomB--");
new Timer().schedule(new MyTimerTaskA(), 2000);
}
}
这样就可以实现自定义时间间隔的连环炸了。传统的定时器技术就总结这么多吧~
更多优质文章和资源,请关注公众号:【程序员私房菜】。
Java并发基础02. 传统线程技术中的定时器技术的更多相关文章
- Java并发基础01. 传统线程技术中创建线程的两种方式
传统的线程技术中有两种创建线程的方式:一是继承Thread类,并重写run()方法:二是实现Runnable接口,覆盖接口中的run()方法,并把Runnable接口的实现扔给Thread.这两种方式 ...
- Java并发基础03. 传统线程互斥技术—synchronized
在多个线程同时操作相同资源的时候,就会遇到并发的问题,如银行转账啊.售票系统啊等.为了避免这些问题的出现,我们可以使用synchronized关键字来解决,下面针对synchronized常见的用法做 ...
- Java并发基础05. 传统线程同步通信技术
先看一个问题: 有两个线程,子线程先执行10次,然后主线程执行5次,然后再切换到子线程执行10,再主线程执行5次--如此往返执行50次. 看完这个问题,很明显要用到线程间的通信了, 先分析一下思路:首 ...
- Java并发编程(02):线程核心机制,基础概念扩展
本文源码:GitHub·点这里 || GitEE·点这里 一.线程基本机制 1.概念描述 并发编程的特点是:可以将程序划分为多个分离且独立运行的任务,通过线程来驱动这些独立的任务执行,从而提升整体的效 ...
- Java并发:搞定线程池(中)
向线程池提交任务 1.1 execute() 用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功.输入的是一个Runnable实例. public void execute(Ru ...
- java并发基础(五)--- 线程池的使用
第8章介绍的是线程池的使用,直接进入正题. 一.线程饥饿死锁和饱和策略 1.线程饥饿死锁 在线程池中,如果任务依赖其他任务,那么可能产生死锁.举个极端的例子,在单线程的Executor中,如果一个任务 ...
- Java 并发基础
Java 并发基础 标签 : Java基础 线程简述 线程是进程的执行部分,用来完成一定的任务; 线程拥有自己的堆栈,程序计数器和自己的局部变量,但不拥有系统资源, 他与其他线程共享父进程的共享资源及 ...
- 【搞定 Java 并发面试】面试最常问的 Java 并发基础常见面试题总结!
本文为 SnailClimb 的原创,目前已经收录自我开源的 JavaGuide 中(61.5 k Star![Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识.欢迎 Sta ...
- java并发基础(二)
<java并发编程实战>终于读完4-7章了,感触很深,但是有些东西还没有吃透,先把已经理解的整理一下.java并发基础(一)是对前3章的总结.这里总结一下第4.5章的东西. 一.java监 ...
随机推荐
- Layabox 世界坐标和屏幕坐标互转
最近在入坑Layabox,花了几天时间做世界坐标和屏幕坐标的互转,由于Layabox没有现成的代码所以只能自己手动写,大概就是模仿unity里面的ScreenToWorldPoint和WorldToS ...
- 无损卡尔曼滤波UKF(3)-预测-生成Sigma点
无损卡尔曼滤波UKF(3)-预测-生成Sigma点 1 选择创建Sigma点 A 根据 已知上一个时间戳迭代出来的 后验状态 x_{k|k} 和后验协方差矩阵 P_{k|k} 他们代表当前状态的分布. ...
- 2020Ubuntu server1804最新安装后的配置
一.Putty进行ssh连接. 完成最基本配置之后,就远程连接服务器了.在windows是我习惯putty 在我以前的老电脑里面找一个putty是0.6版本的,连上Ip ,还是原来的配方,还是原来的味 ...
- django验证码框架captcha
1.安装 2.在settings.py 安装app中添加 3.添加url 4.运行makemigrations和migrate 5.运用 在form表单中定义 view中返回form表单 在前端htm ...
- 性能测试进阶:(一)性能测试工具Locust
An open source load testing tool. 一个开源性能测试工具. define user behaviour with python code, and swarm your ...
- 028.核心组件-API Server
一 Kubernetes API Server原理 1.1 API Server功能 Kubernetes API Server的核心功能是提供Kubernetes各类资源对象(如Pod.RC.Ser ...
- js 实现图片的放大和缩小
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- can do / will do / should do 情态动词
can do = be able to do will do = be going to do should do = ought to do 情态动词 都是表示建议 从这里发现 to do (不确定 ...
- 聊聊OkHttp实现WebSocket细节,包括鉴权和长连接保活及其原理!
一.序 OkHttp 应该算是 Android 中使用最广泛的网络库了,我们通常会利用它来实现 HTTP 请求,但是实际上它还可以支持 WebSocket,并且使用起来还非常的便捷. 那本文就来聊聊, ...
- ArchLinux - 脚本安装使用指南
前面不想废话,讲什么脚本说明,功能什么的!只讲使用方法,其他的可以去Gitee看,去Github看. 脚本虽然支持Boot和UEFI,但是我打算一起讲,因为它们安装时的区别,只有3处不同. 第一步 先 ...