102-Java的定时器、线程并发、并行、线程生命周期中的6种状态

补充知识

一、定时器

1、概述
  • 定时器是一种控制任务延时调用,或者周期调用的技术。
  • 作用:闹钟、定时邮件发送。


2、实现方式
方式一:Timer

Timer定时器

(1)构造器
构造器说明
public Timer()创建Timer定时器对象

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

package com.app.d9_timer;

import java.util.Timer;
import java.util.TimerTask;

/**
    目标:学习Timer定时器的使用
 */
public class TimerDemo1 {
    public static void main(String[] args) {
        // 1、创建Timer定时器
        Timer timer = new Timer();

        // 2、开始一个定时器,按照计划处理TimerTask任务
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "线程执行一次~~");
            }
        }, 3000, 3000); // 程序启动3秒后处理TimerTask任务,每隔3秒会再次处理。
    }
}

在这里插入图片描述


(3)特点和存在的问题
  1. Timer是单线程,处理多个任务按照顺序执行,存在延时与设置定时器的时间有出入。

    在这里插入图片描述

    在这里插入图片描述



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

    package com.app.d9_timer;
    
    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    
    /**
        目标:理解Timer定时器的特点和存在的问题
     */
    public class TimerDemo2 {
        public static void main(String[] args) {
            // 1、创建Timer定时器
            Timer t = new Timer();
    
            // 2、调用方法,开始一个定时器,处理任务
            // A任务,程序启动后0秒后开始执行,每隔2秒执行一次
            t.schedule(new TimerTask() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "线程执行A任务~" + new Date());
                    // A任务执行一次后,线程休眠2秒钟
                    try {
                        Thread.sleep(2000);
                    }catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }, 0, 2000);
    
            // B任务,程序启动后0秒后开始执行,每隔2秒执行一次
            t.schedule(new TimerTask() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "线程执行B任务~" + new Date());
                    System.out.println(10/0);   // 制造一个数学问题的异常!!
                }
            }, 0, 2000);
    
            // C任务,程序启动后0秒后开始执行,每隔2秒执行一次
            t.schedule(new TimerTask() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "线程执行C任务~" + new Date());
                }
            }, 0, 2000);
        }
    }
    

    在这里插入图片描述




方式二:ScheduledExecutorService
  • ScheduledExecutorService是JDK 1.5中引入了并发包,目的是为了弥补Timer的缺陷,ScheduledExecutorService内部为线程池。
(1)Executors的API
方法名称说明
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)获取线程池对象

(2)ScheduledExecutorService的API
方法名称说明
public ScheduledFuture< ? > scheduleAtFixedRate(Runnable command, long initalDelay, long period, TimeUnit unit)周期调度方法

package com.app.d10_scheduledExecutorService;

import java.util.Date;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
    目标:使用ScheduledExecutorService定时器处理定时任务
 */
public class ScheduleExecutorServiceDemo1 {
    public static void main(String[] args) {
        // 1、创建ScheduledExecutorService线程池,做定时器
        ScheduledExecutorService pools = Executors.newScheduledThreadPool(3);

        // 2、开启定时任务
        // A任务,程序启动后0秒后,每隔2秒执行一次
        pools.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "线程执行A任务" + "  时间:" + new Date());
                try {
                    Thread.sleep(100000);   // 让线程进入长时间休眠~~ 模拟线程在忙
                }catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, 0, 2, TimeUnit.SECONDS);


        // B任务,程序启动后0秒后,每隔2秒执行一次
        pools.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "线程执行B任务" + "  时间:" + new Date());
                System.out.println(10 / 0); // 制造一个bug!
            }
        }, 0, 2, TimeUnit.SECONDS);


        // C任务,程序启动后0秒后,每隔2秒执行一次
        pools.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "线程执行C任务" + "  时间:" + new Date());
            }
        }, 0, 2, TimeUnit.SECONDS);
    }
}

在这里插入图片描述


(3)优点
  1. 基于线程池,某个任务的执行情况不会影响其他定时任务的执行。



二、线程并发、并行

1、概述

并发与并行

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

(1)并发的理解
  • CPU同时处理线程的数量是有限的。

    • 比如我电脑的CPU就是4核8个线程(逻辑处理器)的。

    在这里插入图片描述



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

    在这里插入图片描述

    • 不理解的话,我举两个例子:
      • 1、假如咱们班的张老师是一个CPU,咱们都是线程,张老师要给咱们每个人发3颗糖,但由于老师跑得非常快,一下子就给每个人都发了3颗糖,给我们的感觉是同时发糖的,这就是并发执行
      • 2、有一个江湖剑客(CPU),由于他出剑的速度非常的快,一下子就把场上所有的强盗(线程)全部刺杀倒地了,给我们的感觉就好像是一剑全杀的,这就是并发执行


(2)并行的理解
  • 在同一时刻上,同时有多个线程在被CPU处理并执行。

    在这里插入图片描述

    • 不理解的话,我再举个例子:
      • 1、假如我是孙悟空,由于我是一个人,所以每刻只能杀1个妖怪,那要是我弄出6个分身,我就可以每刻杀6个妖怪了,这就是并行

总结

1、简单说说并发与并行的含义是?

  • 并发:CPU分时轮询的执行线程
  • 并行:同一时刻同时在执行



三、线程生命周期

1、概述
  • 生命周期就是从出生到死去。
  • 人一生中会经历很多状态,线程也是一样。

在这里插入图片描述


2、线程的状态
  • 状态:就是线程从生到死的过程,以及中间经历的各种状态及状态转换。
  • 理解线程的状态有利于提升并发编程的理解能力。

3、Java线程的状态
  • Java总共定义了6种状态。

    线程状态说明
    NEW(新建)线程刚被创建,但是并未启动。
    RUNNABLE(可运行)线程已经调用了start()等待CPU调度。
    BLOCKED(锁阻塞)线程在执行的时候未抢到锁对象,则该线程进入BLOCKED状态。
    WAITING(无限等待)一个线程进入WAITING状态,另一个线程调用notify()或者notifyAll()方法才能唤醒。
    TIMED WAITING(计时等待)同WAITING状态,有几个方法有超时参数,调用他们将进入TIMED WAITING状态。
    带有超时参数的常用方法有Thread.sleep、Object.wait。
    TEMINATED(终止)因为run()方法正常终止而死亡,或者因为没有捕获到异常终止了run()方法而死亡。
  • 6种状态都定义在Thread类的内部枚举类中。

    在这里插入图片描述


4、线程的6种状态互相转换

在这里插入图片描述

  • 以下是线程初始化状态后可能会出现的状态:
  • New:线程初始化状态后:
    • 调用start()方法后,等待CPU并发它,被并发后,进入Runnable(可运行状态)
    • 状态1:假如线程在执行小明取钱任务的时候出现了异常,执行完毕,进入Teminated(终止死亡状态)
    • 状态2:假如线程在执行小明取钱任务的时候没有抢到锁,就会进入Blocked(锁阻塞状态)
    • 状态3:假如线程在执行小明取钱任务的时候抢到了锁,就会从Blocked(锁阻塞状态)转换到Runnable(可运行状态)
    • 状态4:假如线程在执行小明取完钱后调用了wait()方法,就会进入Waiting(无限等待状态),假如小明(线程)被小红(其他线程)notify(唤醒)了,但未抢到锁,就会从Waiting(无限等待状态)转换到Blocked(锁阻塞状态)
    • 状态5:假如小明(线程)在Waiting(无限等待状态),被其他线程notify(唤醒)了,并抢到了锁,就会从Waiting(无限等待状态)转换到Runnable(可运行状态)
    • 状态6:假如线程在执行小明调用(sleep(): 抱着锁休眠)wait()方法让小明(线程)进入休眠3秒钟,就会进入到Timed Waiting(计时等待状态)
    • 状态7:假如小明(线程)的(sleep(): 抱着锁休眠)调用结束,说明休眠时间到,从Waiting(计时等待状态)转换到Runnable(可运行状态)
    • 状态8:假如小明(线程)的wait()调用结束,说明休眠时间到,并抢到了锁,从Waiting(计时等待状态)转换到Runnable(可运行状态)
    • 状态9:假如小明(线程)的wait()调用结束,说明休眠时间到,没有抢到锁,就会从Waiting(计时等待状态)转换到Blocked(锁阻塞状态)
    • 状态10:假如线程在执行小明调用wait()方法让小明(线程)进入休眠3秒钟,就会进入到Timed Waiting(计时等待状态),在休眠时间未结束前被小红(其他线程)notify(唤醒)了,并抢到了锁,就会从Waiting(计时等待状态)转换到Runnable(可运行状态)
    • 状态11:假如线程在执行小明调用wait()方法让小明(线程)进入休眠3秒钟,就会进入到Timed Waiting(计时等待状态),在休眠时间未结束前被小红(其他线程)notify(唤醒)了,没有抢到锁,就会从Waiting(计时等待状态)转换到Blocked(锁阻塞状态)
    • 状态12:假如线程在执行小明取钱任务完成,进入Teminated(终止死亡状态)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值