jdk源码分析 – Thread线程类源码分析
首先看到Thread类的声明:
class Thread implements Runnable { /* Make sure registerNatives is the first thing <clinit> does. */
可知,其实现了Runnable接口,而Runnable接口有一个run()方法,所以Thread也实现了该方法。
找到其无参构造函数:
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; }
初始化时设置了是否为守护线程,优先级,初始化名称。
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代码去完成的。
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类也是一个代理类。(他实现了代理模式)
如果你喜欢本文, 请长按二维码,关注公众号 分布式编程.
作者:分布式编程
出处:https://zthinker.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。