线程八大基础核心二(启动线程)

Posted itall

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程八大基础核心二(启动线程)相关的知识,希望对你有一定的参考价值。

 1.引子

在java多线程并发编程中,有八大基础核心。考考你:看看都有哪八大基础核心呢?它们分别是:

  1.创建线程的方式

  2.线程启动

  3.线程停止

  4.线程生命周期

  5.线程相关的方法

  6.线程相关的属性

  7.线程异常处理

  8.线程安全

今天我们从第二个基础核心开始:启动线程

 

2.考考你

#前情回顾:

1.在java编程语言中,创建好线程对象后,通过调用start方法,启动线程

Thread t1 = new Thread();

t1.start();

 

#考考你:

1.问题一:可以调用两次start方法吗?

2.问题二:可以调用run方法,启动线程吗?

 

3.两次调用start方法

package com.anan.thread.startthread;

/**
 * 两次调用start方法,启动线程
 */
public class TwoStartMethodDemo {

    public static void main(String[] args) {

        // 创建Runnable和Thread对象
        Runnable r1 = new MyRunnable();
        Thread t1 = new Thread(r1);

        // 调用两次start方法
        t1.start();
        t1.start();

    }
}

/**
 * 实现Runnable方式,创建线程
 */
class MyRunnable implements Runnable{

    public void run() {
        System.out.println("两次调用start方法启动线程");
    }
}

技术图片

 

4.直接调用run方法

package com.anan.thread.startthread;

/**
 * 直接调用run方法启动线程
 */
public class RunMethodDemo {

    public static void main(String[] args) {
        // 创建Runnable和Thread对象
        Runnable r1 = new MyRunnable2();
        Thread t1 = new Thread(r1);

        // 调用run方法
        t1.run();

    }
}

/**
 * 实现Runnable方式,创建线程
 */
class MyRunnable2 implements Runnable{

    public void run() {
        System.out.println("调用run方法启动线程,当前线程:"+Thread.currentThread().getName());
    }
}

技术图片

 

 

5.线程启动流程分析

5.1.方法源码分析:start

/**
     * 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()
     *
     *注释:启动线程start方法源码,启动线程的流程是:
     *    第一:判断当前线程状态
     *    第二:将当前线程加入线程组
     *    第三:调用本地方法start0(),启动新线程
     */
    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".
         */
        // 第一:判断当前线程状态,如果不是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(),启动新线程
            // 彩蛋:java编程语言的线程实现,是基于操作系统【内核】线程的方式实现
            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 */
            }
        }
    }

技术图片

 

 

5.2.方法源码分析: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)
     *
     *注释:运行线程run方法源码,在方法内部:
     *    第一:调用了target对象的run方法
     *    第二:target对象是Runnable对象,相当于普通对象调用方法
     *    第三:因此不会开启新的线程,还是在主线程main中执行
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

 

6.讨论分享

#线程启动流程:

1.在java编程语言中,正确的启动线程方式,是调用start方法

2.在start方法内部启动流程是:

  2.1.判断当前线程状态,是否是NEW状态

  2.2.如果当前线程是NEW状态,将当前线程加入线程组

  2.3.调用本地方法start0(),开启线程

 

#考考你答案:

1.可以调用两次start方法吗?

答案:不能,因为线程只有在NEW状态下,可以启动

2.可以调用run方法,启动线程吗?

答案:不能,因为直接调用run方法,相当于在主线程main下调用普通方法,并没有开启新的线程

 

以上是关于线程八大基础核心二(启动线程)的主要内容,如果未能解决你的问题,请参考以下文章

线程八大基础核心六(线程属性)

线程八大基础核心四(线程生命周期)

线程八大基础核心一(创建线程的方式)

线程八大基础核心五(线程相关方法一)

3.线程的八大核心基础知识之如何正确停止线程

笔记-线程八大核心总纲