java Thread
一. Thread类与object类等其他类一样,刚开始就有一个
private static native void registerNatives(); static { registerNatives(); }
这个本地方法是为了让这个class的所有本地方法(例如C)可以自定义名称,而不是使用默认名称Java_java_lang_Thread_getClass
二. Thread实现Runnable接口。如果自定义一个线程class,有两种方法:
1.继承Thread,并重载run方法。
* <p><hr><blockquote><pre> * class PrimeThread extends Thread { * long minPrime; * PrimeThread(long minPrime) { * this.minPrime = minPrime; * } * * public void run() { * // compute primes larger than minPrime * . . . * } * } * </pre></blockquote><hr> * <p> * The following code would then create a thread and start it running: * <p><blockquote><pre> * PrimeThread p = new PrimeThread(143); * p.start(); * </pre></blockquote> * <p>
2.实现Runnable接口。也需要实现run方法
* <p><hr><blockquote><pre> * class PrimeRun implements Runnable { * long minPrime; * PrimeRun(long minPrime) { * this.minPrime = minPrime; * } * * public void run() { * // compute primes larger than minPrime * . . . * } * } * </pre></blockquote><hr> * <p> * The following code would then create a thread and start it running: * <p><blockquote><pre> * PrimeRun p = new PrimeRun(143); * new Thread(p).start(); * </pre></blockquote> * <p>
第一种方法,PrimeThread在调用start方法的时候,会把当前的线程加入到线程组中,JVM在native中执行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 || this != me) throw new IllegalThreadStateException(); group.add(this); start0(); if (stopBeforeStart) { stop0(throwableFromStop); } }
第二种方法,PrimeRun新建一个对象后,需要把这个对象引用到Thread对象中,再调用start方法。
public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); }
public void run() { if (target != null) { target.run(); } }
三. 在Thread初始化过程中
/** * Initializes a Thread. * * @param g the Thread group * @param target the object whose run() method gets called * @param name the name of the new Thread * @param stackSize the desired stack size for the new thread, or * zero to indicate that this parameter is to be ignored. */ 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; }
这个方法大意就是通过安全管理器确认当前线程的权限,另外通过这个初始化,可以看出当前线程继承了父线程的DaemonThread(或者Non-DaemonThread)和Priority。