线程——线程实现方式和线程属性
进程和线程
进程是计算机系统中能独立运行并作为资源分配的基本单位,它是由pcb(进程控制块),数据段和代码段组成,是一个能独立运行的基本单位.进程的创建,调度,分派都需要较大的时间和空间开销,在操作系统中引入线程,以线程作为调度和分派的基本单位,以此来改进多处理机系统的性能
线程是操作系统能够进行运算调度的最小单位,同一个进程中的多条线程共享该进程中的全部系统资源
进程与线程的区别:
- 进程每次调度时,都需要进行上下文切换将断点的信息保存在pcb中,开销较大.线程调度时,只需要保存和设置少量的寄存器内容,切换代价比较小
- 进程作为系统资源分配的基本单位,拥有一定的资源,包括用于存放程序,数据的磁盘和内存地址空间,以及在它运行时所需要的i/o设备,已打开的信号量等.而线程只拥有一点必不可少的,能保证独立运行的资源(如控制线程运行的tcb,用于指示被执行指令序列的程序计数器,保存局部变量,少数状态参数和返回地址等的一组寄存器和堆栈),允许多个线程共享该进程中的内存地址空间和资源
java中实现线程的两种方式
java中允许程序并发地运行多个线程,并发是指同一时间间隔中有两个或多个事件同时发生,并行是指同一时刻有两个或多个事件同时执行.
1. 继承thread类并重写run()方法
thread表示线程类,run方法中是我们启动线程时要做的事,应该使用start()方法启动线程,直接调用run方法相当于普通的方法调用,下面我们通过继承thread类的方式定义了一个线程类用来输出0到9,接着在main方法中创建两个线程类的实例并启动线程,可以看出线程的执行情况是随机的.线程的调度细节取决于操作系统,抢占式的线程调度给每个线程一个时间片的时间运行该线程,当该时间片完时,系统会保存当前线程的状态,然后终止当前线程的执行,执行另一个线程,当下一个时间片完时,又会终止当前执行线程,依次类推.直到所有线程终止.
1 public class firstthread extends thread{ 2 @override 3 public void run() { 4 for(int i = 0;i<10;i++) { 5 system.out.println(thread.currentthread().getname()+"打印"+i); 6 } 7 } 8 } 9 public class firstdemo { 10 public static void main(string[] args) { 11 thread thread = new firstthread(); 12 thread thread2 = new firstthread(); 13 thread.start(); 14 thread2.start(); 15 } 16 }
2.实现runnable接口
thread类有一个参数为runnable对象的构造函数,它可以使用给定的runnable对象创建一个线程.
1 public class firstthread implements runnable{ 2 @override 3 public void run() { 4 for(int i = 0;i<10;i++) { 5 system.out.println(thread.currentthread().getname()+"打印"+i); 6 } 7 } 8 } 9 public class firstdemo { 10 public static void main(string[] args) { 11 thread thread = new thread(new firstthread()); 12 thread thread2 = new thread(new firstthread()); 13 thread.start(); 14 thread2.start(); 15 } 16 }
线程属性
线程名(默认thread-线程初始化时的序号)
1 private string name; 2 3 // 设置线程的名字 4 public final synchronized void setname(string name) { 5 checkaccess(); // 检查是否允许更改线程的参数 6 7 if (name == null) { 8 throw new nullpointerexception("name cannot be null"); 9 } 10 11 this.name = name; 12 if (threadstatus != 0) { // 判断线程的状态 13 setnativename(name); 14 } 15 } 16 17 // 获取线程的名字 18 public final string getname() { 19 return name; 20 }
线程的优先级(默认是父线程的优先级)
1 private int priority; 2 3 public final static int min_priority = 1; // 线程的最小优先级 4 5 public final static int norm_priority = 5; // 线程的默认优先级 6 7 public final static int max_priority = 10; // 线程的最大优先级 8 9 // 设置线程的优先级 10 public final void setpriority(int newpriority) { 11 threadgroup g; 12 checkaccess(); // 安全检查 13 14 // 检查设定的优先级是否大于最大优先级或最小优先级,如果是抛出参数不合法异常 15 if (newpriority > max_priority || newpriority < min_priority) { 16 throw new illegalargumentexception(); 17 } 18 19 // 获取当前的线程组 20 if((g = getthreadgroup()) != null) { 21 // 如果当前设定的优先级大于它所在线程组的最大优先级 22 if (newpriority > g.getmaxpriority()) { 23 // 设置当前线程的优先级为当前线程组的最大优先级 24 newpriority = g.getmaxpriority(); 25 } 26 // 调用本地方法setpriority0设置线程优先级 27 setpriority0(priority = newpriority); 28 } 29 } 30 31 // 获取当前线程的优先级 32 public final int getpriority() { 33 return priority; 34 } 35
线程是否是守护线程(默认是父线程的值)
守护线程是为其他线程提供服务的线程,当一个程序只剩下守护线程了,java虚拟机就会退出程序,也就是说守护线程是依托用户线程而存在的,用户线程的终止将会导致守护线程终止,不管当前处于什么状态,在使用守护线程时,应该避免守护线程去访问固有的资源,如文件,数据库等.它会在任何一个操作的中间发生中断.
1 private boolean daemon; 2 3 // 设置该线程是否是守护线程 4 public final void setdaemon(boolean on) { 5 // 安全检查 6 checkaccess(); 7 8 // 如果线程处于活动状态,抛出表示没有在线程适当状态操作进行的异常 9 if (isalive()) { 10 throw new illegalthreadstateexception(); 11 } 12 // 设置线程是否为守护线程 13 daemon = on; 14 } 15 // 判断当前线程是否处于活动状态 16 public final native boolean isalive(); 17 18 // 判断当前线程是否是 守护线程 19 public final boolean isdaemon() { 20 return daemon; 21 }
线程的状态
线程的状态使用一个内部静态枚举类表示
1 public enum state { 2 3 new, // 新建状态 4 5 runnable, // 可运行状态 6 7 blocked, // 阻塞状态 8 9 waiting, // 等待状态 10 11 timed_waiting, // 等待一段时间的状态 12 13 terminated; // 终止状态 14 } 15 16 // 获取当前线程的状态 17 public state getstate() { 18 // get current thread state 19 return sun.misc.vm.tothreadstate(threadstatus); 20 }
线程的未捕获异常处理器
线程的run方法没有抛出任何的受查异常,如果在运行时抛出异常,然而并未捕获处理该异常,该线程即将终止,此时就会将该线程和异常作为参数调用未捕获异常处理器的方法,未捕获异常处理器是一个实现uncaughtexceptionhandler接口的类,uncaughtexception是thread的一个静态内部类,它的内部只有一个方法 void uncaughtexception(thread t, throwable e); 该方法将会在线程因未捕获的异常而终止时调用.threadgroup类实现了该接口.thread类有两个uncaughtexceptionhandler接口的变量,一个是默认的处理器(用static修饰),供所有的线程使用,另一个只供当前线程使用.默认情况下这两个变量都为null,线程使用的未捕获异常处理器是该线程组的处理器.
1 // 供当前线程使用 2 private volatile uncaughtexceptionhandler uncaughtexceptionhandler; 3 4 // 获取当前线程的未捕获异常处理器 5 public uncaughtexceptionhandler getuncaughtexceptionhandler() { 6 // 如果当前线程无未捕获异常处理器,则返回该线程所属线程组的处理器 7 return uncaughtexceptionhandler != null ? 8 uncaughtexceptionhandler : group; 9 } 10 // 设置当前线程的未捕获异常处理器 11 public void setuncaughtexceptionhandler(uncaughtexceptionhandler eh) { 12 checkaccess(); 13 uncaughtexceptionhandler = eh; 14 } 15 16 // 供所有线程使用 17 private static volatile uncaughtexceptionhandler defaultuncaughtexceptionhandler; 18 19 // 获取默认的未捕获异常处理器 20 public static uncaughtexceptionhandler getdefaultuncaughtexceptionhandler(){ 21 return defaultuncaughtexceptionhandler; 22 } 23 // 设置默认的未捕获异常处理器 24 public static void setdefaultuncaughtexceptionhandler(uncaughtexceptionhandler eh) { 25 26 // 获取系统安全管理器 27 securitymanager sm = system.getsecuritymanager(); 28 if (sm != null) { 29 // 检查是否允许执行给定权限的请求,如果不允许,抛出securityexception异常 30 sm.checkpermission( 31 32 // 创建一个在线程由于未捕获的异常而突然终止时,设置将要使用的默认处理程序的运行时权限对象 33 new runtimepermission("setdefaultuncaughtexceptionhandler") 34 ); 35 } 36 // 设置默认的未捕获异常处理器 37 defaultuncaughtexceptionhandler = eh; 38 }
1 // threadgroup 实现thread.uncaughtexception接口的源码解析 2 public void uncaughtexception(thread t, throwable e) { 3 // 如果该线程组有父线程组,则使用父线程组的处理器 4 if (parent != null) { 5 parent.uncaughtexception(t, e); 6 } else { 7 8 // 获取默认的未捕获异常处理器 9 thread.uncaughtexceptionhandler ueh = 10 thread.getdefaultuncaughtexceptionhandler(); 11 12 // 如果有默认的异常处理器就使用它 13 if (ueh != null) { 14 ueh.uncaughtexception(t, e); 15 16 } 17 // 否则判断引起线程终止的异常是否是threaddeath的子类,如果是,什么也不做,负责将线程名和堆栈信息输出到标准错误流中,threaddeath是 18 else if (!(e instanceof threaddeath)) { 19 system.err.print("exception in thread \"" 20 + t.getname() + "\" "); 21 e.printstacktrace(system.err); 22 } 23 } 24 }
线程组threadgroup
线程组是一个统一管理线程的集合,除了初始线程组,每个线程组有一个父线程组,线程组也可以包含其他线程组,允许线程访问有关自己的线程组的信息,但是不允许它访问有关其线程组的父线程组或其他任何线程组的信息.默认情况下,创建的线程组都属于main线程组.线程组有两个构造方法
线程组属性
1 private final threadgroup parent; // 父线程组,一旦指定不可修改 2 string name; // 线程组名 3 int maxpriority; // 线程组的最大优先级 4 boolean destroyed; // 线程组是否被销毁 5 boolean daemon; // 线程组是否是守护线程组 6 boolean vmallowsuspension; // 虚拟机自动挂起 7 8 int nunstartedthreads = 0; // 线程组中未启动线程的数量 9 int nthreads; // 此线程组包含的线程数 10 thread[] threads[]; // 该线程组中包含的线程 11 12 int ngroups; // 子线程组计数器 13 threadgroup[] groups; // 该线程组中包含的线程组
1 构造函数调用顺序从上到下 2 3 //使用指定的线程组名构造线程组 4 public threadgroup(string name) { 5 // 获取当前线程组的父线程组 6 this(thread.currentthread().getthreadgroup(), name); 7 } 8 9 //创建一个父线程组时指定线程,并且名字为name的线程组 10 public threadgroup(threadgroup parent, string name) { 11 // 检查父线程组 12 this(checkparentaccess(parent), parent, name); 13 } 14 15 16 //检查线程组的安全 17 private static void checkparentaccess(threadgroup parent) { 18 parent.checkaccess(); 19 return null; 20 } 21 //安全检查 22 public final void checkaccess() { 23 securitymanager security = system.getsecuritymanager(); 24 if (security != null) { 25 security.checkaccess(this); 26 } 27 } 28 29 private threadgroup(void unused, threadgroup parent, string name) { 30 // 设置线程组名 31 this.name = name; 32 // 最大优先级是父线程组的最大优先级 33 this.maxpriority = parent.maxpriority; 34 // 是否是守护线程组合父线程组保持一致 35 this.daemon = parent.daemon; 36 // 虚拟机参数 37 this.vmallowsuspension = parent.vmallowsuspension; 38 this.parent = parent; 39 parent.add(this); 40 } 41 // 添加指定的线程组 42 private final void add(threadgroup g) { 43 synchronized (this) { 44 // 如果线程组已经被销毁,抛出异常 45 if (destroyed) { 46 throw new illegalthreadstateexception(); 47 } 48 // 判断此线程组子线程组数组是否为空或已满 49 // 如果为空,创建子线程数组,初始容量为4,将指定线程组加入该数组,计数器加一; 50 // 如果子线程数组已满,数组容量扩容两倍,将指定线程组存入数组,计数器加一 51 // 如果子线程数组未满,将指定线程组加入该数组,计数器加一 52 if (groups == null) { 53 groups = new threadgroup[4]; 54 } else if (ngroups == groups.length) { 55 groups = arrays.copyof(groups, ngroups * 2); 56 } 57 groups[ngroups] = g; 58 ngroups++; 59 } 60 }
其他方法
1 // 移除指定的线程组 2 private void remove(threadgroup g) { 3 synchronized (this) { 4 // 判断该线程组是否死亡 5 if (destroyed) { 6 return; 7 } 8 // 循环遍历子线程组数组,找到要删除的线程组,如果找到,子线程组计数器减一 9 // 将处于该线程组元素后的元素向前移动,将最后一个元素置空,跳出循环 10 for (int i = 0; i < ngroups; i++) { 11 if (groups[i] == g) { 12 ngroups -= 1; 13 system.arraycopy(groups, i + 1, groups, i, ngroups - i); 14 groups[ngroups] = null; 15 break; 16 } 17 } 18 19 // 唤醒在此对象上所有等待的线程 20 if (nthreads == 0) { 21 notifyall(); 22 } 23 // 如果此线程组同时满足以下条件,销毁该线程组及其子组 24 // 1. 是守护线程组 25 // 2. 包含的线程数为0 26 // 3. 未启动线程数量为0 27 // 4. 包含的线程组数为0 28 if (daemon && (nthreads == 0) && (nunstartedthreads == 0) && (ngroups == 0)) { 29 destroy(); 30 } 31 } 32 } 33 34 // 将指定线程加入该线程组 35 void add(thread t) { 36 synchronized (this) { 37 if (destroyed) { 38 throw new illegalthreadstateexception(); 39 } 40 if (threads == null) { 41 threads = new thread[4]; 42 } else if (nthreads == threads.length) { 43 threads = arrays.copyof(threads, nthreads * 2); 44 } 45 threads[nthreads] = t; 46 nthreads++; 47 // 为了防止线程组被销毁,未启动线程数递减 48 nunstartedthreads--; 49 } 50 } 51 52 // 移除指定的线程 53 private void remove(thread t) { 54 synchronized (this) { 55 if (destroyed) { 56 return; 57 } 58 for (int i = 0; i < nthreads; i++) { 59 if (threads[i] == t) { 60 system.arraycopy(threads, i + 1, threads, i, --nthreads - i); 61 threads[nthreads] = null; 62 break; 63 } 64 } 65 } 66 } 67 68 // 获得该线程组的名字 69 public final string getname() { 70 return name; 71 } 72 73 // 获得该线程组的最大优先级 74 public final int getmaxpriority() { 75 return maxpriority; 76 } 77 78 // 获得该线程组的父线程组 79 public final threadgroup getparent() { 80 if (parent != null) 81 parent.checkaccess(); 82 return parent; 83 } 84 85 // 判断该线程组是否是守护线程组 86 public final boolean isdaemon() { 87 return daemon; 88 } 89 90 // 判断该线程组是否被销毁 91 public synchronized boolean isdestroyed() { 92 return destroyed; 93 } 94 95 // 设置该线程组的最大优先级 96 public final void setmaxpriority(int pri) { 97 int ngroupssnapshot; 98 threadgroup[] groupssnapshot; 99 100 synchronized (this) { 101 checkaccess(); 102 // 判断给定优先级是否符合要求,不符合要求直接返回 103 if (pri < thread.min_priority || pri > thread.max_priority) { 104 return; 105 } 106 107 // 如果当前线程组没有父线程组,最大优先级就为给定的值 108 // 否则判断父线程组最大优先级和指定优先级,取最小值为该线程组的最大优先级 109 maxpriority = (parent != null) ? math.min(pri, parent.maxpriority) : pri; 110 111 // 获取该线程子线程组的快照(如果存在的话 112 ngroupssnapshot = ngroups; 113 if (groups != null) { 114 groupssnapshot = arrays.copyof(groups, ngroupssnapshot); 115 } else { 116 groupssnapshot = null; 117 } 118 } 119 // 遍历该线程组的所有子线程组,递归将最大优先级设置为指定值 120 for (int i = 0; i < ngroupssnapshot; i++) { 121 groupssnapshot[i].setmaxpriority(pri); 122 } 123 } 124 125 // 设置该线程组是否是守护线程 126 public final void setdaemon(boolean daemon) { 127 checkaccess(); 128 this.daemon = daemon; 129 } 130 131 // 测试此线程组是否是指定线程组的祖先 132 public final boolean parentof(threadgroup g) { 133 for (; g != null; g = g.parent) { 134 if (g == this) { 135 return true; 136 } 137 } 138 return false; 139 } 140 141 // 销毁此线程组及其子组 142 public final void destroy() { 143 int ngroupssnapshot; 144 threadgroup[] groupssnapshot; 145 synchronized (this) { 146 checkaccess(); 147 // 如果线程组已经销毁或该线程组还有活动的线程,抛出一个异常 148 if (destroyed || (nthreads > 0)) { 149 throw new illegalthreadstateexception(); 150 } 151 // 获取子线程组的快照(如果存在的话) 152 ngroupssnapshot = ngroups; 153 if (groups != null) { 154 groupssnapshot = arrays.copyof(groups, ngroupssnapshot); 155 } else { 156 groupssnapshot = null; 157 } 158 159 // 如果该线程组存在父线程组,将各种属性置空 160 if (parent != null) { 161 destroyed = true; 162 ngroups = 0; 163 groups = null; 164 nthreads = 0; 165 threads = null; 166 } 167 } 168 // 循环遍历子线程组,对每个子线程组进行递归处理 169 for (int i = 0; i < ngroupssnapshot; i += 1) { 170 groupssnapshot[i].destroy(); 171 } 172 173 // 如果一个线程组存在父线程组,从父线程组中移除该线程组 174 if (parent != null) { 175 parent.remove(this); 176 } 177 } 178 179 // 获得此线程组中活动的线程数 180 public int activecount() { 181 int result; 182 int ngroupssnapshot; 183 threadgroup[] groupssnapshot; 184 synchronized (this) { 185 if (destroyed) { 186 return 0; 187 } 188 result = nthreads; 189 ngroupssnapshot = ngroups; 190 if (groups != null) { 191 groupssnapshot = arrays.copyof(groups, ngroupssnapshot); 192 } else { 193 groupssnapshot = null; 194 } 195 } 196 for (int i = 0; i < ngroupssnapshot; i++) { 197 result += groupssnapshot[i].activecount(); 198 } 199 return result; 200 } 201 202 // 获得此线程组中活动的线程组数 203 public int activegroupcount() { 204 int ngroupssnapshot; 205 threadgroup[] groupssnapshot; 206 synchronized (this) { 207 if (destroyed) { 208 return 0; 209 } 210 ngroupssnapshot = ngroups; 211 if (groups != null) { 212 groupssnapshot = arrays.copyof(groups, ngroupssnapshot); 213 } else { 214 groupssnapshot = null; 215 } 216 } 217 int n = ngroupssnapshot; 218 for (int i = 0; i < ngroupssnapshot; i++) { 219 n += groupssnapshot[i].activegroupcount(); 220 } 221 return n; 222 } 223 224 // 将此线程组的有关信息输出到标准输出流 225 public void list() { 226 list(system.out, 0); 227 } 228 229 void list(printstream out, int indent) { 230 int ngroupssnapshot; 231 threadgroup[] groupssnapshot; 232 synchronized (this) { 233 for (int j = 0; j < indent; j++) { 234 out.print(" "); 235 } 236 out.println(this); 237 indent += 4; 238 for (int i = 0; i < nthreads; i++) { 239 for (int j = 0; j < indent; j++) { 240 out.print(" "); 241 } 242 out.println(threads[i]); 243 } 244 ngroupssnapshot = ngroups; 245 if (groups != null) { 246 groupssnapshot = arrays.copyof(groups, ngroupssnapshot); 247 } else { 248 groupssnapshot = null; 249 } 250 } 251 for (int i = 0; i < ngroupssnapshot; i++) { 252 groupssnapshot[i].list(out, indent); 253 } 254 } 255 256 // 返回此此类的字符串描述:类名+线程组名+最大优先级 257 public string tostring() { 258 return getclass().getname() + "[name=" + getname() + ",maxpri=" + maxpriority + "]"; 259 } 260 261 // 中断线程组中所有线程和子线程组 262 public final void interrupt() { 263 int ngroupssnapshot; 264 threadgroup[] groupssnapshot; 265 synchronized (this) { 266 checkaccess(); 267 // 中断包含的线程 268 for (int i = 0; i < nthreads; i++) { 269 threads[i].interrupt(); 270 } 271 ngroupssnapshot = ngroups; 272 if (groups != null) { 273 groupssnapshot = arrays.copyof(groups, ngroupssnapshot); 274 } else { 275 groupssnapshot = null; 276 } 277 } 278 // 遍历子线程组,递归处理每一个子线程组 279 for (int i = 0; i < ngroupssnapshot; i++) { 280 groupssnapshot[i].interrupt(); 281 } 282 } 283 284 // 将线程组的所有活动线程复制到指定数组中。如果存在第二个参数,第二个参数为true表示包含子组中的活动线程,默认包含子组中的所有活动线程数, 285 // 当给定的数组不足以容纳该线程组的活动线程数时,忽略额外的线程,因此,最好调用activecount方法确定是否小于list的长度 286 public int enumerate(thread list[]) { 287 checkaccess(); 288 return enumerate(list, 0, true); 289 } 290 291 public int enumerate(thread list[], boolean recurse) { 292 checkaccess(); 293 return enumerate(list, 0, recurse); 294 } 295 296 private int enumerate(thread list[], int n, boolean recurse); 297 298 // 将线程组的所有活动子组复制到指定数组中。如果存在第二个参数,第二个参数为true表示包含子组中的活动子组,默认包含子组中的所有活动子组, 299 // 当给定的数组不足以容纳该线程组的活动子组数时,忽略额外的子组,因此,最好调用activegroupcount方法确定是否小于list的长度 300 301 public int enumerate(threadgroup list[]) { 302 checkaccess(); 303 return enumerate(list, 0, true); 304 } 305 306 public int enumerate(threadgroup list[], boolean recurse) { 307 checkaccess(); 308 return enumerate(list, 0, recurse); 309 } 310 311 private int enumerate(threadgroup list[], int n, boolean recurse); 312 313 // 允许java虚拟机在内存不足是挂起 314 @deprecated 315 public boolean allowthreadsuspension(boolean b); 316 317 // 停止此线程组中的所有线程,不安全 318 @deprecated 319 public final void stop(); 320 321 // 挂起此线程组中的所有线程。 容易导致死锁 322 @deprecated 323 public final void suspend(); 324 325 // 继续此线程组中的所有线程。容易导致死锁 326 @deprecated 327 public final void resume(); 328 329 }
线程thread
1 // 公开的构造函数本质上都是先调用四个参数的init方法,然后调用六个参数的私有init方法构造线程对象 2 3 public thread() { 4 // 调用无参构造时设置线程的名字,然后调用四个参数的私有init方法,由init方法去调用六个参数的init方法 5 init(null, null, "thread-" + nextthreadnum(), 0); 6 } 7 8 // 构造一个新的thread对象,使用指定的运行对象 9 public thread(runnable target) { 10 // 设置线程的名字,调用四个参数的init方法,由init方法去调用六个参数的init方法 11 init(null, target, "thread-" + nextthreadnum(), 0); 12 } 13 14 // 构造一个指定线程组,使用指定运行对象的thread对象 15 public thread(threadgroup group, runnable target) { 16 init(group, target, "thread-" + nextthreadnum(), 0); 17 } 18 19 // 构造一个指定线程名的thread对象 20 public thread(string name) { 21 init(null, null, name, 0); 22 } 23 24 // 构造一个指定线程组和名字的thread对象 25 public thread(threadgroup group, string name) { 26 init(group, null, name, 0); 27 } 28 29 // 构造一个具有指定运行对象和名字的thread对象 30 public thread(runnable target, string name) { 31 init(null, target, name, 0); 32 } 33 34 // 构造一个具有指定线程组,运行对象和名字的thread对象 35 public thread(threadgroup group, runnable target, string name) { 36 init(group, target, name, 0); 37 } 38 39 // 构造一个具有指定线程组,运行对象,名字和堆栈大小的thread对象 40 public thread(threadgroup group, runnable target, string name, 41 long stacksize) { 42 init(group, target, name, stacksize); 43 } 44 45 // 这个构造器不是公开的,他将创建一个 46 thread(runnable target, accesscontrolcontext acc) { 47 init(null, target, "thread-" + nextthreadnum(), 0, acc, false); 48 } 49 50 // 公开的构造函数先调用这个方法 51 private void init(threadgroup g, runnable target, string name, 52 long stacksize) { 53 init(g, target, name, stacksize, null, true); 54 } 55 56 private void init(threadgroup g, runnable target, string name, long stacksize, accesscontrolcontext acc,boolean inheritthreadlocals) { 57 // 如果给定的线程名是null抛出空指针异常 58 if (name == null) { 59 throw new nullpointerexception("name cannot be null"); 60 } 61 // 设置线程名 62 this.name = name; 63 // 获取父线程 64 thread parent = currentthread(); 65 // 获取安全管理器 66 securitymanager security = system.getsecuritymanager(); 67 68 // 如果未指定线程所在的线程组 69 if (g == null) { 70 // 如果安全管理器存在,就使用安全管理器的方法返回当前线程的线程组 71 if (security != null) { 72 g = security.getthreadgroup(); 73 } 74 75 // 如果所属的线程组还是没有,就使用父线程的线程组作为该线程的线程组 76 if (g == null) { 77 g = parent.getthreadgroup(); 78 } 79 } 80 // 判断当前线程是否有权限修改此g线程组,该方法时threadgroup的 81 g.checkaccess(); 82 83 // 检查是否有权限 84 if (security != null) { 85 // 验证是否可以构造该实例 86 if (isccloverridden(getclass())) { 87 security.checkpermission(subclass_implementation_permission);// 验证是否有指定的运行时权限 88 } 89 } 90 // 增加线程组中未启动线程的数量。 91 g.addunstarted(); 92 93 // 设置线程相关属性,获取父线程的相关属性作为该线程的相关属性(如果未指定) 94 this.group = g; 95 this.daemon = parent.isdaemon(); 96 this.priority = parent.getpriority(); 97 if (security == null || isccloverridden(parent.getclass())) 98 this.contextclassloader = parent.getcontextclassloader(); 99 else 100 this.contextclassloader = parent.contextclassloader; 101 this.inheritedaccesscontrolcontext = 102 acc != null ? acc : accesscontroller.getcontext(); 103 this.target = target; 104 setpriority(priority); 105 if (inheritthreadlocals && parent.inheritablethreadlocals != null) 106 this.inheritablethreadlocals = 107 threadlocal.createinheritedmap(parent.inheritablethreadlocals); 108 this.stacksize = stacksize; 109 tid = nextthreadid(); 110 }
threadgroup,thread,thread.state,thread.uncaughtexception之间的类图
上一篇: Java JDBC结果集的处理
下一篇: 忘记埋在哪个位置了