暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

1.线程Thread源码探究

阿亮的日志 2021-03-17
293

前言

本篇内容主要分析多线程中的核心类Thread
的使用,从源码级别入口。学习线程的初始化以及启动中的一些流程。

课程目标

  • 1.线程Thread的初始化以及启动方法的核心流程
  • 2.后台线程Dameon
  • 3.join()的应用场景及原理
  • 4.interrupt()的应用
  • 5.wait()与notify()

1. Thread
类的源码解析

1.1.初始化流程

入口方法: init(g, target, name, stackSize, null, true);

  • 1.把当前线程设置为新线程的父线程
  • 2.每个线程都会有一个线程组(ThreadGroup),若没有指定,则线程组就是父线程的线程组
  • 3.当前线程的daemon默认为父线程的daemon状态
  • 4.线程优先级默认是父线程的优先级
  • 5.线程id是全局递增,从1开始。

1.2. 启动流程

入口方法 public synchronized void start()

  public synchronized void start() {
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        group.add(this);
        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
            }
        }
  }

  • 1.threadStatus
    默认为0,线程一旦执行过之后,就会变为非0的状态,此时现在不能再次被start();
  • 2.你启动线程之后,这个线程就会加入之前处理好的那个线程组中
  • 3.启动一个线程实际上走的是native方法,start0(),会实际的启动一个线程
  • 4.一个线程启动之后就会执行run()方法

2.Daemon(后台线程)

又称为守护线程,当工作线程都停止的话,那么Daemon
会跟着jvm进程一起退出;

即可设置为后台线程
thread.setDaemon(true);

3.join()的应用场景及原理

  • 如果在main线程中调用其他线程,则main线程和其他线程会并发执行。
  • 如果在main线程中调用了另一个线程的join,那么main线程就会阻塞住,等待其他线程执行完毕。
  • 如下代码,我们实现一个注册功能,必须要先完成注册再进行心跳,所以在主线程中我们就先阻塞主线程等待完成之后再进行心跳

如下图代码,如果没有执行registerWorker.join();
,那么就会出现注册完成之前,调用heartbeatWorker.start();
从而出现注册完成之前,先发送心跳的情况。

  public void start() {
    try {
      // 一旦启动了这个组件之后,他就负责在服务上干两个事情
      // 第一个事情,就是开启一个线程向register-server去发送请求,注册这个服务
      // 第二个事情,就是在注册成功之后,就会开启另外一个线程去发送心跳

      // 我们来简化一下这个模型
      // 我们在register-client这块就开启一个线程
      // 这个线程刚启动的时候,第一个事情就是完成注册
      // 如果注册完成了之后,他就会进入一个while true死循环
      // 每隔30秒就发送一个请求去进行心跳
      RegisterWorker registerWorker = new RegisterWorker();
      registerWorker.start();
      registerWorker.join();

      heartbeatWorker.start();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

4.interrupt()的应用

在一个线程中调用另一个线程的interrupt()方法,即会向那个线程发出信号——线程中断状态已被设置。至于那个线程何去何从,由具体的代码实现决定。

public class InterruptDemo {

  public static void main(String[] args) throws InterruptedException {
    MyThread t1 = new MyThread();
    t1.start();
    Thread.sleep(1000);
    t1.setShouldRun(false);
    t1.interrupt();
    System.out.println(">>>>>>>>>>>>>>>>>>>>>"+t1.isInterrupted());
  }

  private static class MyThread extends Thread{
    private boolean shouldRun = true;

    @Override
    public void run() {
      while (shouldRun){
        try {
          System.out.println(Thread.currentThread().getName()+"正在工作......");
          Thread.sleep(30*1000);
        }catch (Exception e){
          e.printStackTrace();
        }
      }
    }

    public void setShouldRun(boolean shouldRun){
      this.shouldRun = shouldRun;
    }
  }
}

主要应用与中断其他线程的休眠,和sleep结合,用于标志位的处理。

5.wait()与notify()


文章转载自阿亮的日志,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论