定时器
- 定时器是一种控制任务延时调用,或者周期调用的技术。
作用:
闹钟、定时邮件发送。
定时器的实现方式
- 方式一:Timer
- 方式二: ScheduledExecutorService
Timer定时器
/**
* 目标;Timer定时器的使用和了解
*/
public class TimerDemo1 {
public static void main(String[] args) {
//1、创建Timer定时器
Timer timer = new Timer();//定时器本身就是一个单线程
timer.schedule(new TimerTask() {//匿名内部类形式 参数分别为:任务,延时时间3秒(启动之后隔多少秒开始执行),启动之后每隔2秒执行一次
@Override
public void run() {
//逻辑
System.out.println(Thread.currentThread().getName()+"执行一次~~~");
}
},3000,2000);
}
}
Timer定时器的特点和存在的问题
- 1、Timer是单线程,处理多个任务按照顺序执行,存在延时与设置定时器的时间有出入。
timer.schedule(new TimerTask() {//匿名内部类形式
/*一个线程执行两个任务*/
@Override
public void run() {
//逻辑
System.out.println(Thread.currentThread().getName() + "执行一次AAA~~~" + new Date());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 0, 2000);
timer.schedule(new TimerTask() {
@Override
public void run() {
//逻辑
System.out.println(Thread.currentThread().getName() + "执行一次BBB~~~" + new Date());
}
}, 0, 2000);
- 2、可能因为其中的某个任务的异常使Timer线程死掉,从而影响后续任务执行。
timer.schedule(new TimerTask() {
@Override
public void run() {
//逻辑
System.out.println(Thread.currentThread().getName() + "执行一次AAA~~~" + new Date());
System.out.println(10/0);
}
}, 0, 2000);
timer.schedule(new TimerTask() {
@Override
public void run() {
//逻辑
System.out.println(Thread.currentThread().getName() + "执行一次BBB~~~" + new Date());
}
}, 0, 2000);
如图:
因为是一个线程处理所有任务,当一个任务出现异常的时候,这个异常会抛给线程(因为是线程调用的),而线程没有捕获异常,它就把异常抛给虚拟机,虚拟机直接将程序干掉。
ScheduledExecutorService定时器
- ScheduledExecutorService是 jdk1.5中引入了并发包,目的是为了弥补Timer的缺陷, ScheduledExecutorService内部为线程池。
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class TimerDemo2 {
public static void main(String[] args) {
//1、创建ScheduledExecutorService线程池,做定时器
ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);
//2、开启定时任务
pool.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"执行输出:AAA");
}
},0,2, TimeUnit.SECONDS);
}
}
运行结果:
ScheduledExecutorService的优点
- 1、基于线程池,某个任务的执行情况不会影响其他定时任务的执行
public class TimerDemo2 {
public static void main(String[] args) {
//1、创建ScheduledExecutorService线程池,做定时器
ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);
//2、开启定时任务
pool.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"执行输出:AAA"+new Date());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},0,2, TimeUnit.SECONDS);
/*现在是线程池,上边的线程被任务占用后,下边的任务还有其他的线程负责定时调度*/
pool.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"执行输出:BBB"+new Date());
}
},0,2, TimeUnit.SECONDS);
}
}
运行结果:
pool.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"执行输出:BBB"+new Date());
System.out.println(10/0);
}
},0,2, TimeUnit.SECONDS);
pool.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"执行输出:CCC"+new Date());
}
},0,2, TimeUnit.SECONDS);
运行结果:
并发与并行
- 正在运行的程序(软件)就是一个独立的进程, 线程是属于进程的,多个线程其实是并发与并行同时进行的。
并发的理解:
- CPU同时处理线程的数量有限。
- CPU会轮询为系统的每个线程服务,由于CPU切换的速度很快,给我们的感觉这些线程在同时执行,这就是并发。
并行的理解:
- 在同一个时刻上,同时有多个线程在被CPU处理并执行。
简单说说并发和并行的含义
- 并发:CPU分时轮询的执行线程。
- 并行:同一个时刻同时在执行,并行依赖于你CPU的逻辑处理器,比如你的CPU是16线程的,那意味着CPU可以同时处理16个线程。
线程的生命周期
人的状态
线程的状态
- 线程的状态:也就是线程从生到死的过程,以及中间经历的各种状态及状态转换。
- 理解线程的状态有利于提升并发编程的理解能力
Java线程的状态
- Java总共定义了6种状态
- 6种状态都定义在Thread类的内部枚举类中。
线程的6种状态互相转换