以上是百科对线程的描述。知道了什么是线程,我们就来看看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()方法启动线程时时有明显的区别的,会用自己的方式启动线程。此处贴图一张(别人的解释):