并发之Thread源码解读

Runnable与Thread没有根本性的区别,Runnable定位为一个功能性接口,如下:

@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接口,添加了更多的方法和属性

public
class Thread implements Runnable {
    /* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
        registerNatives();
    }

    private volatile char  name[];
    private int            priority;
    private Thread         threadQ;
    private long           eetop;

    /* Whether or not to single_step this thread. */
    private boolean     single_step;

    /* Whether or not the thread is a daemon thread. */
    private boolean     daemon = false;

    /* JVM state */
    private boolean     stillborn = false;

    /* What will be run. */
    private Runnable target;

    /* The group of this thread */
    private ThreadGroup group;

    /* The context ClassLoader for this thread */
    private ClassLoader contextClassLoader;

    /* The inherited AccessControlContext of this thread */
    private AccessControlContext inheritedAccessControlContext;

    /* For autonumbering anonymous threads. */
    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }

    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;

    /*
     * InheritableThreadLocal values pertaining to this thread. This map is
     * maintained by the InheritableThreadLocal class.
     */
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

    ... ...
    ... ...

而网上部分观点说Runnable可实现资源共享也是有误的

Thread的run()与start()方法

run方法是执行了super.target的run()方法,而start()方法才是创建了一系列过程,最后通过native方法start0()回调回重写的run方法,以下是Thread源码中的两个方法的源码

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
   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 */
            }
        }
    }

其中主要三步:判断线程状态、加入线程组、执行native方法start0()

    /* Java thread status for tools,
     * initialized to indicate thread 'not yet started'
     */
    //初始状态就是为0
    private volatile int threadStatus = 0;

start() 是一个 synchronized 方法,但为了避免多次调用,在方法中会由线程状态判断。threadStatus != 0。在new Thread时会被初始化为0

    public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }

而threadStatus是在线程从创建到结束生命周期中,由JVM控制的,如下:

    public State getState() {
        // get current thread state
        return sun.misc.VM.toThreadState(threadStatus);
    }

状态有以下几种:

VM.class

    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;
        }
    }

以上是按位与计算的,也就是二进制位置对其,都为1时才为1,否则为0,eg:var0 & 1 ==0 =>0&1=0,则标识var0当前状态为0.

如果threadStatus=0初始化状态,则加入线程组,默认初始数组长度为4。一个线程必须有自己所属的线程组,且一但加入则不能更改,加入线程组可以方便管理线程,比如设置优先级、守护线程等。

    /* The group of this thread */
    private ThreadGroup group;

最后执行本地方法start0()。(一般java底层方法名带0的都是native方法)这一步的操作才是启动线程的核心步骤。后续都是jvm代码了,不做展开。

线程创建到执行的过程简单描述如下:

1、Java 创建线程和启动;

2、调用本地方法 start0();

3、JVM 中 JVM_StartThread 创建和启动Thread;

4、设置线程状态等待被唤醒;

5、根据不同的OS启动线程并唤醒;

6、最后回调 run() 方法启动 Java 线程。

实现案例

1、继承Thread,并重写start方法,调用start即可

public class ThreadA extends Thread {

    @Override
    public void start(){
        System.out.println("ThreadA");
    }

}

调用start的

2、实现Runnable接口,重写run方法并调用run方法触发

public class RunnableA implements Runnable {
    @Override
    public void run() {
        System.out.println("RunnableA");
    }
}

以上执行demo如下

public class Test {
    public static void main(String[] args) {
        ThreadA threadA = new ThreadA();
        RunnableA runnableA = new RunnableA();
        threadA.start(); //打印结果:ThreadA
        runnableA.run(); //打印结果:RunnableA
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值