JDK源码阅读(8):Thread类

  

       以上是百科对线程的描述。知道了什么是线程,我们就来看看JAVA中Thread类的声明:

public class Thread implements Runnable {
    //很惊喜吧?和Object类一个套路,创建对象的那一刹那先绑定一些系统函数。
    private static native void registerNatives();
    static {
        registerNatives();
    }

    //volatile关键字修饰来保证name属性的线程可见性
    private volatile String name;

    //优先级
    private int            priority;
    private Thread         threadQ;
    private long           eetop;

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

    //是否守护进程
    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;

    //用来统计初始化了多少个线程的(static修饰,所有实例化对象共享。)
    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;

    /*
     * The requested stack size for this thread, or 0 if the creator did
     * not specify a stack size.  It is up to the VM to do whatever it
     * likes with this number; some VMs will ignore it.
     */
    private long stackSize;

    /*
     * JVM-private state that persists after native thread termination.
     */
    private long nativeParkEventPointer;

    /*
     * Thread ID
     */
    private long tid;

    //线程序列化编号
    private static long threadSeqNumber;

    /* Java thread status for tools,
     * initialized to indicate thread 'not yet started'
     */

    private volatile int threadStatus = 0;
}

       通过以上的代码,号线干啥也看不出来,就是定义了好多的属性,也不知道干什么用的。我们先不管,先来看看Thread类的构造方法:

     

    所有的构造方法最后都指向了一个init()方法,代码如下:

   private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }

        this.name = name;

        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();
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        this.target = target;
        setPriority(priority);
        if (inheritThreadLocals && 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();
    }

 第一个点是name值的自动生成,是通过"Thread-" + nextThreadNum()方式生成的。nextThreadNum()方法代码如下:

    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }

 需要注意Thread类内部维护了一个当前被初始化了的线程数量计数器。被static修饰保证了所有Thread类的实例可以共享。

第二个点是下面第一行代码和currentThread()方法的声明,native关键字修饰表示该方法是其他语言来做的事情。也就是说,新建的Thread实例被挂在了当前线程的名下,作为当前线程子线程被标记。

Thread parent = currentThread();

public static native Thread currentThread();

第三个点是下面第一行代码,它调用System的getSecurityManager()中得到了SecurityManager,从名称就大致可以猜出来,它是和系统权限管理相关的。System的SecurityManager对象来自于org.quartz.impl.QuartzServer类的main方法启动程序时实例化出来的java.rmi.RMISecurityManager对象(再深入下去的话,就跑偏了。。)。

SecurityManager security = System.getSecurityManager();

public class System
      public static void main(String[] args) throws Exception {

        //    //Configure Log4J
        //    org.apache.log4j.PropertyConfigurator.configure(
        //      System.getProperty("log4jConfigFile", "log4j.properties"));

        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new java.rmi.RMISecurityManager());
        }
      }
}

  我们再来看看为什么Thread类在实例化时需要系统权限,下面是init()方法中的部分代码,很明确的干了一件事,就是将参数ThreadGroup置为未启动状态。

       ThreadGroup g;
       SecurityManager security = System.getSecurityManager();
        if (g == null) {
            if (security != null) {
                g = security.getThreadGroup();
            }
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }
        g.checkAccess();
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }
        g.addUnstarted();

接下来,我们来看看Thread怎么处理Runnable接口的run()方法的:

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

  可以看到,这种方式启动Thread的话,和普通的Runable接口实现类没啥区别,那Thread定义了那么多属性基本上没啥意义。那我们就来看看Thread的start()方法:

    public synchronized void start() {
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        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();

所以,Thread的start()和Runnable接口的run()方法启动线程时时有明显的区别的,会用自己的方式启动线程。此处贴图一张(别人的解释):

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值