线程生命周期&线程交互方式

  1. 操作系统线程状态
    在这里插入图片描述

    • 初始状态:线程已经被创建但是不允许分配cpu执行,在编程层面线程已经创建,但在操作系统层面真正的线程还没有创建
    • 可运行状态:可以分配cpu执行此线程,这种状态下操作系统层面线程已经创建,所以可以分配cpu执行
    • 运行状态:当有空闲线程执行时,线程状态变成运行状态,没有空闲cpu执行时为可运行状态
    • 休眠状态:当调了阻塞或等待的api时,会释放cpu使用权,等待被唤醒,线程状态变成休眠状态,当等待的事件出现了,线程就会从休眠状态转换到可运行状态。
    • 终止状态:线程执行完或者出现异常就会进入终止状态,终止状态的线程不会切换到其他任何状态,进入终止状态也就意味着线程的生命周期结束了。
  2. java层面的线程状态
    在这里插入图片描述

    • NEW:初始化状态
    • RUNNABLE:运行状态包括可运行状态与运行状态
    • BLOCKED:阻塞状态【只针对于syncronized竞争没拿到锁】
    • WAITING:无时限等待
    • TIMED_WAITING:有时限等待
    • TERMINATED:终止状态
  3. java线程的创建方式【本质只有一种,都是通过new Thread()创建线程,调用Thread#start启动线程,最终都会调用Thread#run方法】

    • 继承thread类,底层使用的runable接口

      // 创建线程对象
      Thread t = new Thread() {
          public void run() {
          // 要执行的任务
          }
      };
      // 启动线程
      
    • 实现runnable接口配合thread类,run()方法没有返回值,不抛出异常

      Runnable runnable = new Runnable() {
          public void run(){
          // 要执行的任务
          }
      };
      // 创建线程对象
      Thread t = new Thread( runnable );
      // 启动线程
      
    • 实现callable接口结合线程池使用,有返回值,抛异常,线程池里面的线程也是new thread实现的

      class CallableTask implements Callable<Integer> {
          @Override
          public Integer call() throws Exception {
              return new Random().nextInt();
          }
      }
      //创建线程池
      ExecutorService service = Executors.newFixedThreadPool(10);
      //提交任务,并用 Future提交返回结果
      
    • 使用lamda表达式

      new Thread(() -> System.out.println(Thread.currentThread().getName())).start();
      
  4. 内核级线程与用户级线程
    在这里插入图片描述

    • 内核级线程【java属于内核线程】:它们是依赖于内核的,即无论是用户进程中的线程,还是系统进程中的线程,它们的创建、撤消、切换都由内核实现。
    • 用户级线程:操作系统内核不知道应用线程的存在。
  5. java线程调度机制

    • 协同式线程调度:线程执行时间由线程本身来控制
      • 线程把自己的工作执行完之后,要主动通知系统切换到另外一个线程上。
      • 好处:实现简单,且切换操作对线程自己是可知的,没啥线程同步问题
      • 坏处:线程执行时间不可控制,如果一个线程有问题,可能一直阻塞在那里。
    • 抢占式线程调度【java调度就是抢占式线程调度】
      • 每个线程将由系统来分配执行时间,线程的切换不由线程本身来决定【(Java中,Thread.yield()可以让出执行时间,但无法获取执行时间)】
      • 好处:线程执行时间系统可控,也不会有一个线程导致整个进程阻塞。
  6. thread的常见方法

    • sleep方法

      • 线程状态从Running进入TIMED_WAITING状态
      • 基于线程,不释放对象锁
      • 清除中断标识,需捕获中断异常
      • 睡眠结束的线程必定会得到cpu执行权
      • 当参数传0时,效果与yield相同
    • yield方法

      • 释放cpu资源,线程状态从running进入runnable状态
      • 基于线程,不释放对象锁
      • 会清除中断标志,需捕获中断异常
      • 当前只有一个main方法时,调用yield方法后main方法会立即执行,因为没有比他优先级更高的线程
      • 具体执行完全依赖操作系统调度
    • join方法

      • 主线程调子线程的join方法,主线程会等到子线程执行完成之后才会执行【基于等待通知】

      • 代码实现

        public class ThreadJoinDemo {
        
            public static void main(String[] sure) throws InterruptedException {
        
                Thread t = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("t begin");
                        try {
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("t finished");
                    }
                });
                long start = System.currentTimeMillis();
                t.start();
                //主线程等待线程t执行完成
                t.join();
        
                System.out.println("执行时间:" + (System.currentTimeMillis() - start));
                System.out.println("Main finished");
            }
        
    • await方法

      • 会释放锁,清除标志位【基于对象,对象都实现了monter机制,会释放锁】
    • stop方法

      • 已经被jdk废弃,原因就是stop()方法太过于暴力,强行把执行到一半的线程终止。
      • stop会释放对象锁,可能会造成数据不一致。
  7. Java线程的中断机制

    • 中断机制是一种协作机制,也就是说通过中断并不能直接终止另一个线程,而需要被中断的线程自己处理

    • API的使用

      • interrupt():将线程中断标志位设置成true,不会停止线程
      • isInterrupted(): 判断当前线程的中断标志位是否为true,不会清除中断标志位
      • Thread.interrupted():判断当前线程的中断标志位是否为true,并清除中断标志位,重置为fasle,只会生效一次
    • 一些坑

      • sleep可以被中断 抛出中断异常:sleep interrupted, 清除中断标志位

      • wait可以被中断 抛出中断异常:InterruptedException, 清除中断标志位

      • 处于休眠中的线程被中断,线程是可以感受到中断信号的,并且会抛出一个 InterruptedException 异常,同时清除中断信号,将中断标记位设置成 false。需要在catch中重新手动添加中断信号,不做任何处理,就会屏蔽中断请求,有可能导致线程无法正确停止。

    • 优雅停止线程

      • 利用中断机

        while (!Thread.currentThread().isInterrupted() && more work to do) {
            do more work
        }
        
      • 使用中断机制时一定要注意是否存在中断标志位被清除的情况

  8. 等待唤醒机制

    • wait方法
      • monter机制实现的,需要再同步代码块中实现,没有绑定线程
    • notify方法
      • monter机制实现的,需要再同步代码块中实现,没有绑定线程
  9. LockSupport等待唤醒

    • 概念:LockSupport是JDK中用来实现线程阻塞和唤醒的工具,线程调用park则等待许可,调用unpark则为指定线程提供许可

    • park:等待一个许可,有许可后可以一直执行下去

    • unPark:入参是一个线程,为指定线程parkTread提供许可,如果在park之前执行,线程在park时可以拿到许可继续执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值