前面我们已经对多线程的基础知识有了一定的了解,那么接下来我们将要对多线程进一步深入的学习;但在学习之前我们还是要对传统的技术进行一次回顾,本章我们回顾的则是:传统线程技术和传统的定时器实现.

一、传统线程技术

1.创建方式

1、继承thread类

Thread t = new Thread(){
@Override
public void run() {
}
};
t.start();

2、实现Runnable接口

Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
}
}
});
t1.start();

3、实现Callable接口

ExecutorService pool = Executors.newCachedThreadPool();
Future future = pool.submit(new Callable() {
public Object call() throws Exception {
return null;
}
});

2.比较

1、Thread VS Runnable

  • java不支持多继承,允许实现多个接口。Thread是类,Runnable是接口
  • Runnable适合于资源的共享(多个Thread使用相同的Runnable)
  • public class Thread extends Object implements Runnable. Thread是Runnable接口的子类

2、Runnable VS Callable

  • Callable的 call() 方法可以返回Future类型结果和抛出异常,而Runnable的run()方法没有这些功能
  • Callable通常利用ExecutorService的submit方法去启动call方法,Runnable还可以通过Thread的run方法启动run方法

二、传统定时器Timer

1、创建

到点执行,参数(TimerTask task, Date time),或者(TimerTask task, long delay)延迟多久后执行

new Timer().schedule(new TimerTask() {
@Override
public void run() {
}
}, new Date());

延迟多久执行,然后定时执行,参数(TimerTask task, long delay, long period)或者(TimerTask task, Date firstTime, long period)到点执行,然后定时执行

new Timer().schedule(new TimerTask() {
@Override
public void run() {
}, 1000, 5000})

还有类似的scheduleAtFixedRate(TimerTask task, long delay, long period)scheduleAtFixedRate(TimerTask task, Date firstTime,long period)

2、schedule和scheduleAtFixedRate区别

  • 2个参数的schedule:如果当前时间超过第一次执行时间,则立即执行,否则到定时时间执行
  • 3个参数的schedule:如果当前时间超过第一次执行时间,则立即执行,否则到定时时间执行。下一个任务执行一定是在上一个任务执行完之后执行。下一次任务执行的时间需要看上一个任务执行多久exceTime及周期时间period,如果exceTime>period则立即执行,否则等待period时间再执行。
  • scheduleAtFixedRate:每个任务执行的时间应该是定下了的。如果中间有作业处理时间太长导致后面的不能如期定时执行,则会立即执行后面的作业,直到追上了某一个任务的定时。如果当前时间超过第一次执行时间,则后面所有的作业都会立即执行,直到追上了某一个任务的定时。因为fixed-rate,可能导致同一时间重复执行,所以TimerTask中的执行体需要考虑同步(不是很懂)

schedule示例:

new Timer().schedule(new TimerTask(){
public void run() {
try {
System.out.println("execute task! "+ dateFormatter.format(this.scheduledExecutionTime()));
Random random = new Random();
int slpTime = random.nextInt(3)*1000 + 4000;
System.out.println("exec time:" + slpTime);
Thread.sleep(slpTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},startDate, 5 * 1000);

输出结果:

execute task!  2017-12-14 23:26:22 // 当前时间超过了设定了首次执行时间,立即执行
exec time:1000 // 第一次执行时间为1s小于周期时间2s
execute task! 2017-12-14 23:26:24 // 所以第二次在第一次执行时间2s之后执行
exec time:2000 // 第三次次执行时间为2s刚好等于周期时间2s
execute task! 2017-12-14 23:26:26 // 所以第三次在第二次执行时间2s之后执行
exec time:3000 // 第三次执行时间为3s大于周期时间2s
execute task! 2017-12-14 23:26:29 // 所以第四次在第三次执行时间3s之后执行
exec time:1000 // 之后就类似
execute task! 2017-12-14 23:26:31
exec time:2000
execute task! 2017-12-14 23:26:33
exec time:3000
execute task! 2017-12-14 23:26:36
exec time:1000
execute task! 2017-12-14 23:26:38

scheduleAtFixedRate示例:

System.out.println("start time: " + dateFormatter.format(new Date()));
new Timer().scheduleAtFixedRate(new TimerTask(){
int i = 0;
int slpTimes[] = new int[] {2000,4000,100,100,100};
public void run() {
try {
System.out.println("execute task:" + i + "! "+ dateFormatter.format(this.scheduledExecutionTime()) + " now time: " + dateFormatter.format(new Date())) ;
int slpTime = slpTimes[i++%slpTimes.length];
System.out.println("exec time:" + slpTime);
Thread.sleep(slpTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},startDate, 2 * 1000);

输出结果:

start time: 2017-12-15 00:00:09                                     //开始执行时间未到定时
execute task:0! 2017-12-15 00:01:00 now time: 2017-12-15 00:01:00 //定时开始执行
exec time:2000 //刚好执行2s
execute task:1! 2017-12-15 00:01:02 now time: 2017-12-15 00:01:02 //所以第二次在规定时间执行
exec time:4000 //第二次执行2s,导致第三次延迟执行(第三次应该在2017-12-15 00:01:04执行)
execute task:2! 2017-12-15 00:01:04 now time: 2017-12-15 00:01:06 //第三次在2017-12-15 00:01:06执行
exec time:100 //第三次执行100ms
execute task:3! 2017-12-15 00:01:06 now time: 2017-12-15 00:01:06 //因为之前导致了延迟,需要追赶,所以立即执行,以下类似
exec time:100
execute task:4! 2017-12-15 00:01:08 now time: 2017-12-15 00:01:08
exec time:100
execute task:5! 2017-12-15 00:01:10 now time: 2017-12-15 00:01:10
exec time:2000
execute task:6! 2017-12-15 00:01:12 now time: 2017-12-15 00:01:12

3、Timer的缺陷

Timer的替代品ScheduledExecutorService,这个不在本文进行介绍,后面会进行阐述ScheduledExecutorService.

参考资料:

《多线程视频》张孝祥

JAVA多线程提高一:传统线程技术&传统定时器Timer的更多相关文章

  1. Java基础_死锁、线程组、定时器Timer

    一.死锁问题: 死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放.由于线程被无限期地阻塞,因此程序不可能正常终止. 比如,线程一需要第一把所,此时锁处于空闲状态,给了 ...

  2. JAVA多线程提高三:线程范围内共享变量&ThreadLocal

    今天我们学习的是如何在线程自己的范围内达到变量数据的共享,而各个线程之间又是互相独立开来,各自维护的,即我们说的ThreadLocal的作用. 一.概念 可以将每个线程用到的数据与对应的线程号存放到一 ...

  3. Java并发基础02. 传统线程技术中的定时器技术

    传统线程技术中有个定时器,定时器的类是Timer,我们使用定时器的目的就是给它安排任务,让它在指定的时间完成任务.所以先来看一下Timer类中的方法(主要看常用的TimerTask()方法): 前面两 ...

  4. Java多线程-同步:synchronized 和线程通信:生产者消费者模式

    大家伙周末愉快,小乐又来给大家献上技术大餐.上次是说到了Java多线程的创建和状态|乐字节,接下来,我们再来接着说Java多线程-同步:synchronized 和线程通信:生产者消费者模式. 一.同 ...

  5. Java多线程(二) —— 线程安全、线程同步、线程间通信(含面试题集)

    一.线程安全 多个线程在执行同一段代码的时候,每次的执行结果和单线程执行的结果都是一样的,不存在执行结果的二义性,就可以称作是线程安全的. 讲到线程安全问题,其实是指多线程环境下对共享资源的访问可能会 ...

  6. Java多线程(一) —— 线程的状态详解

    一.多线程概述  1. 进程 是一个正在执行的程序.是程序在计算机上的一次运行活动. 每一个进程执行都有一个执行顺序.该顺序是一个执行路径,或者叫一个控制单元. 系统以进程为基本单位进行系统资源的调度 ...

  7. Java多线程(五)线程的生命周期

    点我跳过黑哥的卑鄙广告行为,进入正文. Java多线程系列更新中~ 正式篇: Java多线程(一) 什么是线程 Java多线程(二)关于多线程的CPU密集型和IO密集型这件事 Java多线程(三)如何 ...

  8. Java多线程(一) —— 传统线程技术

    一.传统线程机制 1. 使用类Thread实现 new Thread(){ @Override public void run() { while(true){ try{ Thread.sleep(2 ...

  9. 【java并发】传统线程技术中创建线程的两种方式

    传统的线程技术中有两种创建线程的方式:一是继承Thread类,并重写run()方法:二是实现Runnable接口,覆盖接口中的run()方法,并把Runnable接口的实现扔给Thread.这两种方式 ...

随机推荐

  1. 2018软工实践—Alpha冲刺(5)

    队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 协助测试的进行 测试项目运行的服务器环境 ...

  2. Java中按值传递与按引用传递的区别

    值传递:(形式参数类型是基本数据类型):方法调用时,实际参数把它的值传递给对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形式参数值的改变不影响 ...

  3. alpha冲6

    队名:日不落战队 安琪(队长) 今天完成的任务 回收站前端界面. 明天的计划 查看个人信息界面. 还剩下的任务 信息修改前端界面. 设置界面. 遇到的困难 模拟机莫名其妙就崩了,调试了很久,后在队友的 ...

  4. 关于虚拟机安装mac os 教程详解

    环境搭建 VMware下载 百度云盘下载:链接:http://pan.baidu.com/s/1pK8RcLl 密码:5jc5 Unlocker208 百度云盘下载:链接:http://pan.bai ...

  5. 关于解决java读取excel文件遇空行抛空指针的问题 !

    关于解决java读取excel文件遇空行抛空指针的问题 ! package exceRead; import java.io.File; import java.io.FileInputStream; ...

  6. python接口自动化测试框架实现之字符串插入变量(字符串参数化)

    问题: 在做接口自动化测试的时候,请求报文是json串,但是根据项目规则必须转换成字符串,然后在开头拼接“data=” 接口中很多入参值需要进行参数化. 解决方案: 1.Python并没有对在字符串中 ...

  7. ADO.NET DBHelper 类库

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...

  8. IIS部署时failed to execute url 解决方法

    web.config中增加如下节点: <system.webServer>  <validation validateIntegratedModeConfiguration=&quo ...

  9. asp.net mvc4+EF 下使用UEditor

    一.从官方网站下载UEditor,http://ueditor.baidu.com/website/download.html, 我下载的是1.53.net版本

  10. bzoj2383[CEOI2011] ballons

    题意 在一条数轴上从左向右有一些气球,每个气球一开始位于横坐标xi的位置,是半径为0的圆.现在开始从左向右给每个气球充气.被充气的气球的半径会不断变大,直到达到这个气球的半径上限Ri或者这个气球和之前 ...