首页 > 代码库 > 多线程之线程初始
多线程之线程初始
多线程之线程初始
上章我们讲了线程的概念,这章我们来深入的了解下一个线程整个初始的过程,感谢上次小伙伴们的意见,后面我都会是文字+图片+代码。让大家看的更轻松。
创建一个线程的代码为:
Thread t = new Thread();
但这仅仅仅仅是初始了一个线程(它眼下还什么都不知道仅仅是静静的“坐”在一边),我们来看看这个初始中详细做了哪些事情:
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
能够看到创建线程就是调用了一个初始的方法,再看看每一个參数的解释:
1 param g the Thread group
2 param target the object whose run() method gets called
3 param name the name of the new Thread
4 param stackSize the desired stack size for the new thread, or
zero to indicate that this parameter is to be ignored.
第一个參数就是一个线程组,他的作用就是来方便对线程的统一管理,每个线程都要归属于一个线程组,假设我们不去明白的制定。那么就归属到默认线程组,当然无论是哪个线程组终于都归属于系统线程组,若创建多个线程而不指定一个组,它们就会自己主动归属于系统线程组。
第2个參数是调用run()方法的对象,也就是任务对象本身。
第3个创建线程的名称。
第4个就是堆栈的默认分配空间(默认值是0)
JDK中重载了非常多创建线程的方法,可是详细实现的过程是大同小异:
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();
}
首先会拿到当前线程的对象的引用。然后分配一个线程组(默认线程组选择权最低,參数的选择权最高),然后就是一系列给属性赋值的操作。这里就不细说了,当中有一些重要的属性来说明下:
/* Whether or not to single_step this thread. */
private boolean single_step;
是否为一个简单的线程
/* Whether or not the thread is a daemon thread. */
private boolean daemon = false;
是否是后台线程。 Daemon的作用是为其它线程的执行提供服务,比方说GC线程。
事实上User Thread线程和Daemon Thread守护线程本质上来说去没啥差别的,唯一的差别之处就在虚拟机的离开:假设User Thread所有撤离。那么Daemon Thread也就没啥线程好服务的了,所以虚拟机也就退出了。
/* JVM state */
private boolean stillborn = false;
是否为激活状态。对于线程的状态我们后面会具体的介绍
/* What will be run. */
private Runnable target;
任务实体类对象,详细任务放在继续Runnable接口的run()方法中
/* 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;
这里是继承AccessControlContext类()这里才是真正的线程,而等到线程的方法就是:
this.inheritedAccessControlContext = AccessController.getContext();
this.inheritedAccessControlContext = AccessController.getContext();
事实上这里是用一种调用当前上下文的快照的技术。而我们通常使用的dubug对象也是在AccessController类中,代码:
public final class AccessControlContext {
public final class AccessControlContext {
private ProtectionDomain context[];
private boolean isPrivileged;
private AccessControlContext privilegedContext;
private DomainCombiner combiner = null;
private static boolean debugInit = false;
private static Debug debug = null;
static Debug getDebug()
{
if (debugInit)
return debug;
else {
if (Policy.isSet()) {
debug = Debug.getInstance("access");
debugInit = true;
}
return debug;
}
}
/* For autonumbering anonymous threads. */
private static int threadInitNumber;
这里就是为线程id命名的一个id(是线程id组成的一部分。线程id的结构是“Thread-”+threadInitNumber),这id也是自增的,代码:
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
而在线程初始的时候就给了id,代码:
tid = nextThreadID();
private long stackSize;
堆栈空间,默认jvm会分配
private long tid;
线程id
/* Java thread status for tools,
* initialized to indicate thread ‘not yet started‘
*/
private int threadStatus = 0;
线程状态。可惜的是没备注全部的状态解释和相应的状态值
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;
最小线程的优先权
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;
默认线程的优先权
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;
最大线程的优先权
大致就这些吧,以上是线程中比較重要线程的属性。这会有助于我们跟好的去理解线程的组成和机制
事实上以上只不过说明了线程在jdk层的初始,但从一台电脑来讲,整个线程创建的流程是如何了?
大家都知道在java层调度操作系统时中间另一层jvm。这里本人也没去深究jvm和操作系统之间的通讯,但大致画出了一个创建线程的流程图:
在我们工作中我们实际还是从线程池中去拿。而这又涉及到对线程池工作原理的了解,但在这章我们不做解说。
(从jdk的层面讲)
总之这一章主要是希望让大家明确线程究竟有哪些熟悉。怎样初始。
多线程之线程初始
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。