多线程生命周期和源码分析(1)

x33g5p2x  于2021-08-23 转载在 Java  
字(4.6k)|赞(0)|评价(0)|浏览(109)

前言

多线程入门最佳文章,本文类目图
在这里插入图片描述

一线程介绍

  1. 当操作系统运行一个程序时就会为其创建一个进程(比如启动一个APP,启动一个java程序);
  2. 一个进程里面可以启动多个线程(比如APP某个功能就是一个线程)​;
  3. 线程拥有独立的程序计数器,堆栈,局部变量,共享变量等属性;线程之间由CPU进行高速轮询切换,客户在使用这些线程服务时感觉同时在运行线程​。

二多线程的优势

(1)现代的操作系统基本不会是单核CPU,一般都是多核,多线程能够提高CPU的利用率,让操作系统合理调度资源​,提高客户​体验
(2)多线程能够提高响应效率,举个栗子:去医院排队取号,医院通常会放置多台取号机,每台的取号机都是一个线程,能够同时调度医院程序系统,此时就是类似多线程​;如果只有单台取号机,那么我们就需要付出很大的时间代价去排队取号,那么这个时候就是类似单线程。

三多线程的生命周期

(1)源码获得的线程状态有6种。

public static State toThreadState(int var0) {
        if ((var0 & 4) != 0) {
            return State.RUNNABLE;
        } else if ((var0 & 1024) != 0) {
            return State.BLOCKED;
        } else if ((var0 & 16) != 0) {
            return State.WAITING;
        } else if ((var0 & 32) != 0) {
            return State.TIMED_WAITING;
        } else if ((var0 & 2) != 0) {
            return State.TERMINATED;
        } else {
            return (var0 & 1) == 0 ? State.NEW : State.RUNNABLE;
        }
    }

(2)枚举提供线程状态有6种

public enum State {
 
        NEW,

        RUNNABLE,

        BLOCKED,

        WAITING,

        TIMED_WAITING,

        TERMINATED;
    }

(3)大体的线程生命周期如下图

在这里插入图片描述

【NEW】: 当我们 new Thread 的时候就会创建一个线程,处于NEW状态(注意此时线程没运行);

【RUNNABLE】:当thread调用start()方法的时候就进入了RUNNABLE状态,此时可以说已经具备了被CPU执行的资格,当然也仅仅是资格,就比如你报名参加考试,你有考试的资格,但还没到真正的考试时间。

【RUNNING】: 当较多的线程进入RUNNABLE状态,CPU开始轮询调用,当调用到该线程,那么线程就会进入RUNNING状态;此时也就是在执行用户写的程序代码,就比如此时才是考试时间,开始做题了。

【BLOCKED】:阻塞状态就像排队取号啊,你要排队一直等待啊,等到你的时候才进入RUNNING状态,等待的时候就是阻塞;具体的如何出入BLOCKED看上图。

【TERMINATED】:一般是线程生命周期正常结束就会进入TERMINATED,具体看上图。

【WAITING】: 等待态,这个有些类似阻塞状态,需要等待其他线程特定的动作才能唤醒。​

【TIMED_WAITING】:超时等待态,具体时间到了它会自行返回继续执行线程。

(4)不列方法原因

  1. 已过时的方法:stop(),resume(),suspect(),他们很容易造成CPU资源占用进入睡眠,具有死锁倾向,基于这些副作用会使用等待唤醒机制代替
  2. wait()方法:这个方法其实是java.lang.Object的方法。

四 如何创建线程(Thread)

创建线程方式只有一种就是构造Thread类,实现线程执行的方式有2种;第一种是实现Runnable接口的run()方法,Runnable实例对象传给Thread类,第二种是重写Thread的run方法(又可以分为继承Thread类和匿名内部类方式,匿名内部类还可以用Lamda表示);

(1) 实现Runable接口示例:

/**
 * @Author lsc
 * @Description <p> </p>
 * @Date 2019/10/13 3:02
 * @Version 1.0
 */
public class CreateThread1 implements Runnable{
​
    @Override
    public void run() {
        while (true){
            System.out.println("线程启动");
        }
    }
​
    public static void main(String[] args) {
        Thread thread = new Thread(new CreateThread1());
        thread.start();
    }
}

(2)重写Thread​示例:

/**
 * @Author lsc
 * @Description <p> </p>
 * @Date 2019/10/13 3:11
 * @Version 1.0
 */
public class CreateThread2 {

    public static void main(String[] args) {
        Thread thread = new Thread(() -> System.out.println("启动线程"), "youku1327");
        thread.start();
    }
}

五 Thread源码分析

(1)start()方法

  • start()方法是线程安全的方法,当start()方法开始执行的时候会去调用这个线程的run()方法(run()方法是被JIN编译器的native start0() 所调用);
  • 结果就是这2个线程会并发运行(第一个是调用这个线程的线程,第二个就是被调用的线程);
  • 线程多次运行是非法的,一个已经运行过的线程是不能被重新运行否则会抛出IllegalThreadStateException异常;
  • 线程启动后会被加入线程组;
/**
     * Causes this thread to begin execution; the Java Virtual Machine
     * calls the <code>run</code> method of this thread.
     * <p>
     * The result is that two threads are running concurrently: the
     * current thread (which returns from the call to the
     * <code>start</code> method) and the other thread (which executes its
     * <code>run</code> method).
     * <p>
     * It is never legal to start a thread more than once.
     * In particular, a thread may not be restarted once it has completed
     * execution.
     *
     * @exception  IllegalThreadStateException  if the thread was already
     *               started.
     * @see        #run()
     * @see        #stop()
     */
    public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
​
        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);
​
        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }
    
     private native void start0();

(2)run()方法

  • 通常实现runnable接口是需要创建线程,当线程调用start()的方法的时候会单独的执行run方法;
  • run()方法的约定是可以采取​任何行动。
/**
     * If this thread was constructed using a separate
     * <code>Runnable</code> run object, then that
     * <code>Runnable</code> object's <code>run</code> method is called;
     * otherwise, this method does nothing and returns.
     * <p>
     * Subclasses of <code>Thread</code> should override this method.
     *
     * @see     #start()
     * @see     #stop()
     * @see     #Thread(ThreadGroup, Runnable, String)
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
    
@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

(3)结论

我们从刚刚的分析中可以得到一个结论,start() 的方法只负责启动线程,不负责任何实现逻辑,run()方法只负责实现业务逻辑;线程的控制和业务实现是分离关系。

(4)架构依赖

在这里插入图片描述

相关文章