• jdk源码分析 – Thread线程类源码分析


    1、继承关系:

    首先看到Thread类的声明:

    class Thread implements Runnable {
        /* Make sure registerNatives is the first thing <clinit> does. */

    可知,其实现了Runnable接口,而Runnable接口有一个run()方法,所以Thread也实现了该方法。

    2、构造函数:

    找到其无参构造函数:

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

    这里的第三个参数是设置线程的名称,从下面的代码中可以看出,生成名称的规则是:”Thread-”加上创建的线程的个数(第几个)。

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

    可以看到threadInitNumber是类静态变量。且他的增加是线程安全的。(synchronized )

    继续查看init方法:

    private void init(ThreadGroup g, Runnable target, String name,
                          long stackSize) {
        Thread parent = currentThread();
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
            /* Determine if it's an applet or not */
    
            /* If there is a security manager, ask the security manager
               what to do. */
            if (security != null) {
            g = security.getThreadGroup();
            }
    
            /* If the security doesn't have a strong opinion of the matter
               use the parent thread group. */
            if (g == null) {
            g = parent.getThreadGroup();
            }
        }
        /* checkAccess regardless of whether or not threadgroup is
               explicitly passed in. */
        g.checkAccess();
    
        /*
         * Do we have the required permissions?
         */
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }
    
            g.addUnstarted();
    
        this.group = g;
        this.daemon = parent.isDaemon();
        this.priority = parent.getPriority();
        this.name = name.toCharArray();
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext = AccessController.getContext();
        this.target = target;
        setPriority(priority);
            if (parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
            ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
            /* Stash the specified stack size in case the VM cares */
            this.stackSize = stackSize;
    
            /* Set thread ID */
            tid = nextThreadID();
    
            this.me = this;
        }

    初始化时设置了是否为守护线程,优先级,初始化名称。

    3、Thread的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 || this != me)
                throw new IllegalThreadStateException();
            group.add(this);
            start0();
            if (stopBeforeStart) {
            stop0(throwableFromStop);
        }
        }

    这里主要的是start0方法;查看其实现:

    private native void start0();

    这里使用了本地调用,通过C代码初始化线程需要的系统资源。并同时调用run()方法。

    可见,线程底层的实现是通过C代码去完成的。

    4、Thead的run方法的实现:
    public void run() {
        if (target != null) {
            target.run();
        }
        }

    这里的target实际上要保存的是一个Runnable接口的实现的引用:

    private Runnable target;

    所以使用继承Thread创建线程类时,需要重写run方法,因为默认的run方法什么也不干。

    而当我们使用Runnable接口实现线程类时,为了启动线程,需要先勇该线程类实例初始化一个Thread,实际上就执行了如下构造函数:

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

    即是把线程类的引用保存到target中。这样,当调用Thread的run方法时,target就不为空了,而是继续调用了target的run方法,所以我们需要实现Runnable的run方法。这样通过Thread的run方法就调用到了Runnable实现类中的run方法。

    这也是Runnable接口实现的线程类需要这样启动的原因。

    可见Thread类也是一个代理类。(他实现了代理模式)

  • 相关阅读:
    set-find
    set-equal_range
    set-equal_range
    set-erase
    php 抽象类 静态 单体设计模式
    Servlet 工作原理解析
    职场上一个人情商高的十种表现
    快速学习一门新技术入门
    php中14中排序方式的实现
    php中对Mysql数据库的访问操作
  • 原文地址:https://www.cnblogs.com/daichangya/p/12959986.html
Copyright © 2020-2023  润新知