认识线程Thread

128 阅读4分钟

目录

什么是线程?

线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。

首先,来看一下代码,我们的本意是让ab交替输出

public class TryConcurrency {
    public static void main(String[] args) {
        a();
        b();
    }
    public static void a(){
        while (true) {
            System.out.println("a");
            sleep(1);
        }
        
    }
    public static void b(){
        while (true){
            System.out.println("b");
            sleep(1);
        }
​
    }
    public static void sleep(int s){
        try {
            TimeUnit.SECONDS.sleep(s);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}

但是我们得到的结果却是

image_AWSlrdspGM.png

我们会一直循环一个动作,这时候我们就需要使用Thread类来创建一个新的线程,

public static void main(String[] args) {
        //匿名类的方式
        new Thread(){
            public void run() {
                a();
            }
        }.start();
        //lambda方式
        new Thread(TryConcurrency::a).start();
        b();
    }

此时的运行结果:

image_FG9uVeqCC5.png

线程的生命周期

image_h0ThFLiK44.png

Run()和Start()方法的关系

看到我们调用方式的时候,我们重写的事run()方法,但是,最后调用的时候是调用start()方法,这其中有什么关系,我们打开源码看一下

    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 */
            }
        }
    }

通过源码我们能看见,这个方法主要就是调用了start0() 方法,那我们在进入到这个方法里面,

 private native void start0();
​
    /**
     * 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();
        }
    }
​

这个方法的实现呢就是Runnable 接口中的方法

package java.lang;
@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();
}

那为什么设计者会这么去做呢?

答案很简单就是为了控制和业务逻辑进行分离

真正意义上实现的多线程

在很多软文以及一些书籍中,经常会提到,创建线程有两种方式,第一种是构造一个Thread,第二种是实现Runnable接口,这种说法是错误的,最起码是不严谨的,在JDK中代表线程的就只有Thread这个类,我们在前面分析过,线程的执行单元就是run方法,你可以通过继承Thread然后重写run方法实现自己的业务逻辑,也可以实现Runnable接口实现自己的业务逻辑;现执行单元的两种方式,所以说创建线程有两种方式,一种是创建一个Thread,一种是实现Runnable接口,这种说法是不严谨的。准确地讲,创建线程只有一种方式那就是构造Thread类,而实现线程的执行单元则有两种方式,第一种是重写Thread的run方法,第二种是实现Runnable接口的run方法,并且将Runnable实例用作构造Thread的参数。