多线程之线程初始

上章我们讲了线程的概念,这章我们来深入的了解下一个线程整个初始的过程,感谢上次小伙伴们的意见,后面我都会是文字+图片+代码。让大家看的更轻松。

创建一个线程的代码为:

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();

事实上这里是用一种调用当前上下文的快照的技术。而我们通常使用的dubug对象也是在AccessController类中,代码:

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的层面讲)

总之这一章主要是希望让大家明确线程究竟有哪些熟悉。怎样初始。

时间: 2025-01-04 11:52:16

多线程之线程初始的相关文章

mfc小工具开发之定时闹钟之---多线程急线程同步

一.MFC对多线程编程的支持 MFC中有两类线程,分别称之为工作者线程和用户界面线程.二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环. 工作者线程没有消息机制,通常用来执行后台计算和维护任务,如冗长的计算过程,打印机的后台打印等.用户界面线程一般用于处理独立于其他线程执行之外的用户输入,响应用户及系统所产生的事件和消息等.但对于Win32的API编程而言,这两种线程是没有区别的,它们都只需线程的启动地址即可启动线程来执行任务. 在MFC中,一般用全局函数Afx

MFC——9.多线程与线程同步

Lesson9:多线程与线程同步 程序.进程和线程是操作系统的重点,在计算机编程中,多线程技术是提高程序性能的重要手段.本文主要讲解操作系统中程序.进程和线程之间的关系,并通过互斥对象和事件对象实例说明多线程和线程同步技术. 1.      程序.进程和线程 1.1  程序和进程 程序是计算机指令的集合,它以文件的形式存储在磁盘上.进程通常被定义为一个正在运行的程序的实例,是一个程序在其自身的地址空间中的一次执行活动.进程是资源申请.调度和独立运行的单位,因此,它使用系统中的运行资源:而程序不能

Java多线程之线程的控制

Java多线程之线程的控制 线程中的7 种非常重要的状态:  初始New.可运行Runnable.运行Running.阻塞Blocked.锁池lock_pool.等待队列wait_pool.结束Dead 如果将"锁池"和"等待队列"都看成是"阻塞"状态的特殊情况,那么可以将线程归纳为5个状态: 新建,就绪,运行,阻塞,死亡. ┌--------------------< 阻塞 ↓                    (1)(2)(3)  

iOS开发多线程篇—线程的状态

iOS开发多线程篇—线程的状态 一.简单介绍 线程的创建: self.thread=[[NSThread alloc]initWithTarget:self selector:@selector(test) object:nil]; 说明:创建线程有多种方式,这里不做过多的介绍. 线程的开启: [self.thread start]; 线程的运行和阻塞: (1)设置线程阻塞1,阻塞2秒 [NSThread sleepForTimeInterval:2.0]; (2)第二种设置线程阻塞2,以当前时

Java多线程开发系列之四:玩转多线程(线程的控制1)

在前文中我们已经学习了:线程的基本情况.如何创建多线程.线程的生命周期.利用已有知识我们已经可以写出如何利用多线程处理大量任务这样简单的程序.但是当应用场景复杂时,我们还需要从管理控制入手,更好的操纵多线程.在第一节中我们讲过,使用多线程的好处之一就是我们可以通过编码和已有类库更好的管理和控制多线程.接下来我会详细的介绍如何管理多线程,包括:对线程的等待.守护线程.线程的睡眠.线程的突然停止.线程的让步.线程的优先级等.由于内容比较多,本节先介绍前两部分:对线程的等待.守护线程 1.线程的等待

C#中利用委托实现多线程跨线程操作

在使用VS2005的时候,如果你从非创建这个控件的线程中访问这个控件或者操作这个控件的话就会抛出这个异常.这是微软为了保证线程安全以及提高代码的效率所做的改进,但是也给大家带来很多不便. 其实解决这个问题有两种方法:一,是通过设置System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;在你的程序初始化的时候设置了这个属性,而且在你的控件中使用的都是微软Framework类库中的控件的话,系统就不会再抛出你上面所说的

Java多线程之线程结束清理

该事例说明了清理工作必须要放在finally块中 package Thread.Interrupting; import java.util.concurrent.TimeUnit; class NeedsCleanup { private final int id; public NeedsCleanup(int ident) { id = ident; System.out.println("NeedsCleanup " + id); } public void cleanup()

Java多线程之线程中断

该例子说明,Sleep可以被中断,但是I/O和synchronized不能被中断. package Thread.Interrupting; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; imp

C#多线程之线程池篇3

在上一篇C#多线程之线程池篇2中,我们主要学习了线程池和并行度以及如何实现取消选项的相关知识.在这一篇中,我们主要学习如何使用等待句柄和超时.使用计时器和使用BackgroundWorker组件的相关知识. 五.使用等待句柄和超时 在这一小节中,我们将学习如何在线程池中实现超时和正确地实现等待.具体操作步骤如下: 1.使用Visual Studio 2015创建一个新的控制台应用程序. 2.双击打开"Program.cs"文件,编写代码如下所示: 1 using System; 2 u