Java多线程 - 定时器-并发与并行-线程生命周期

Posted 学全栈的灌汤包

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程 - 定时器-并发与并行-线程生命周期相关的知识,希望对你有一定的参考价值。

文章目录

多线程补充

定时器

定时器介绍:

定时器是一种控制任务延时调用,或者周期调用的技术。

作用:闹钟、定时邮件发送。

定时器实现方式:

方式一:Timer

方式二: ScheduledExecutorService

Timer定时器构造器和方法如下:

构造器说明
public Timer()创建Timer定时器对象
public static void main(String[] args) 
    // 创建一个定时器任务
    Timer timer = new Timer();

方法说明
schedule(TimerTask task, long delay, long period)开启一个定时器,按照计划处理TimerTask任务

参数一: 延时执行的任务

参数二: 延迟的时间

参数三: 每隔多少时间执行一次(不传参数三表示只延迟执行一次)

public static void main(String[] args) 
    // 创建一个定时器任务
    Timer timer = new Timer();

    // 调用方法处理定时任务, 延迟执行三秒后每隔两秒执行一次
    timer.schedule(new TimerTask() 
        @Override
        public void run() 
            System.out.println(Thread.currentThread().getName() + "执行一次");
        
    , 3000, 2000);

Timer定时器的特点和存在的问题

Timer是单线程,处理多个任务按照顺序执行(意味着多个定时器会在一个线程中依次执行, 定时任务就会相互影响),存在延时与设置定时器的时间有出入。

可能因为其中的某个任务的异常使Timer线程死掉,从而影响后续任务执行。


ScheduledExecutorService定时器:

ScheduledExecutorService是 jdk1.5中引入了并发包,目的是为了弥补Timer的缺陷, ScheduledExecutorService内部为线程池。

Executors的方法说明
static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)得到线程池对象
ScheduledExecutorService的方法说明
scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)周期调度方法

演示代码:

public static void main(String[] args) 
    // 创建ScheduledExecutorService线程池做定时器
    ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);

    // 开启定时任务
    pool.scheduleAtFixedRate(new TimerTask() 
        @Override
        public void run() 
            System.out.println(Thread.currentThread().getName() + "执行输出AAA");
        
    , 0, 2, TimeUnit.SECONDS);

    // 多个定时器任务之间不会相互影响
    pool.scheduleAtFixedRate(new TimerTask() 
        @Override
        public void run() 
            System.out.println(Thread.currentThread().getName() + "执行输出BBB");
        
    , 0, 2, TimeUnit.SECONDS);

ScheduledExecutorService的优点:

基于线程池,某个任务的执行情况不会影响其他定时任务的执行。

并发和并行

并发与并行:

正在运行的程序(软件)就是一个独立的进程, 线程是属于进程的,多个线程其实是并发与并行同时进行的

并发的理解:

CPU同时处理线程的数量有限。

CPU会轮流为系统的每个线程服务,由于CPU切换的速度很快,给我们的感觉这些线程在同时执行,这就是并发。

并行的理解:

在同一个时刻上,有多个线程真正的被CPU同时处理并执行。

线程的生命周期

线程的状态:

线程的状态:也就是线程从生到死的过程,以及中间经历的各种状态及状态转换。

理解线程的状态有利于提升并发编程的理解能力。

Java线程的状态:

Java总共定义了6种状态

6种状态都定义在Thread类的内部枚举类中, 如下:

public class Thread
		...
		public enum State 
				NEW,
				RUNNABLE,
      	BLOCKED,
      	WAITING,
      	TIMED_WAITING,
      	TERMINATED;
		
		...

线程中6种状态相互转换如下:

线程状态描述
NEW(新建)线程刚被创建,但是并未启动。
Runnable(可运行)线程已经调用了start()等待CPU调度
Blocked(锁阻塞)线程在执行的时候未竞争到锁对象,则该线程进入Blocked状态;
Waiting(无限等待)一个线程进入Waiting状态,另一个线程调用notify或者notifyAll方法才能够唤醒
Timed Waiting(计时等待)同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。带有超时参数的常用方法有Thread.sleep 、Object.wait。
Teminated(被终止)因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。

6Java并发性和多线程-并发性与并行性

以下内容转自http://tutorials.jenkov.com/java-concurrency/concurrency-vs-parallelism.html(使用谷歌翻译):

术语并发和并行性通常用于多线程程序。但是,并发和并行性究竟是什么意思呢,它们是相同的术语还是什么?

简短的答案是“不”。它们不是相同的术语,尽管它们在表面上看起来非常相似。也花了我一些时间来终于找到并了解并发和并行性之间的区别。因此,我决定在这个Java并发教程中添加一个关于并发性与并行性的文本。

并发

并发意味着应用程序同时在多个任务上同时进行。那么如果计算机只有一个CPU,应用程序可能不会在同一时间在多个任务上进行进展 ,但是在应用程序内一次处理多个任务。在下一个开始之前,它不完全完成一项任务。

并行

并行性意味着应用程序将其任务分解成更小的子任务,可以并行处理,例如在多个CPU上同时进行处理。

并发性与并行性细节

正如你所看到的,并发性与应用程序如何处理它所处理的多个任务有关。应用程序可以在时间(顺序)处理一个任务或同时处理多个任务(并发)。

另一方面,并​​行性与应用程序如何处理每个单独的任务有关。应用程序可以从头到尾连续地处理任务,或将任务分解成可以并行完成的子任务。

你可以看到,应用程序可以是并发的,但不是并行的。这意味着它同时处理多个任务,但任务不会分解为子任务。

应用程序也可以是并行的,但不是并发的。这意味着应用程序一次只能在一个任务上工作,并且该任务被分解成可并行处理的子任务。

另外,应用程序既可以并发也不能并行。这意味着它一次只能执行一个任务,并且任务不会被分解为并行执行的子任务。

最后,一个应用程序也可以并发和并行,因为它同时在多个任务上工作,并且还将每个任务分解成子任务并行执行。但是,在这种情况下,并发和并行性的一些好处可能会丢失,因为计算机中的CPU已经保持合并繁忙,并发或并行性。结合它可能只会导致小的性能增益甚至性能损失。在盲目采用并行并行模型之前,请确保分析和测量。

以上是关于Java多线程 - 定时器-并发与并行-线程生命周期的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程原理+基础知识(超级超级详细)+(并发与并行)+(进程与线程)1

Spring如何处理线程并发问题

java中多线程并发并行线程与进程线程调度创建线程的方式

java中多线程并发并行线程与进程线程调度创建线程的方式

Java多线程与并发——线程生命周期和线程池

6Java并发性和多线程-并发性与并行性