Thread源码解析
来源:互联网 发布:网络机顶盒怎么选 编辑:程序博客网 时间:2024/05/17 09:11
引言
在介绍Thread源码之前先简要介绍一下线程相关的一些基础知识。
线程定义
线程是现代操作系统调度的最小单元,一个进程可以创建多个线程来提高系统的吞吐量和执行效率。
注:进程是操作系统资源分配和调度的基本单位,它可以创建多个线程,进程可创建的线程数量跟操作系统相关。
为什么要使用多线程?
- 更多的处理器核心;
- 更快的响应时间;
- 更好的编程模型:java提供了一套完整的jmm规则,屏蔽了底层的一些操作,开发人员只需要关注自己的业务逻辑即可。
线程的状态
- NEW:初始状态,线程被构建,还未调用start()方法;
- RUNNABLE:运行状态,在java多线程模型中,就绪和运行都是运行状态;
- BLOCKED:阻塞状态;
- WAITING:等待状态,比如中断,需要其他的线程来唤醒;
- TIME_WAITING:超时等待,可以在指定的时间内自行返回;
- TERMINATED:终止状态,线程执行完毕。
Thread源码分析
- 构造线程
构造函数:
//无参构造方法public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0);}//带参构造方法public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0);}public Thread(ThreadGroup group, Runnable target) { init(group, target, "Thread-" + nextThreadNum(), 0);}public Thread(String name) { init(null, null, name, 0);}public Thread(ThreadGroup group, String name) { init(group, null, name, 0);}public Thread(Runnable target, String name) { init(null, target, name, 0);}public Thread(ThreadGroup group, Runnable target, String name) { init(group, target, name, 0);}public Thread(ThreadGroup group, Runnable target, String name, long stackSize) { init(group, target, name, stackSize);}
所有的构造方法都调用了init这个方法,接下来我们就来详细的看看init方法到底是怎么来初始化线程的。
初始化线程:
private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc) { //参数校验,线程name不能为null if (name == null) { throw new NullPointerException("name cannot be null"); } this.name = name.toCharArray(); //当前线程就是该线程的父线程 Thread parent = currentThread(); //获取系统的security SecurityManager security = System.getSecurityManager(); if (g == null) { //security不为null时,线程所在group为security的group if (security != null) { g = security.getThreadGroup(); } //security为null时,直接使用父线程的group if (g == null) { g = parent.getThreadGroup(); } } g.checkAccess(); //授权 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 (parent.inheritableThreadLocals != null) //创建线程共享变量副本 this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); this.stackSize = stackSize; //分配线程id tid = nextThreadID();}
- 启动线程
public synchronized void start() { //假若当前线程初始化还未做好,不能start,0->NEW状态 if (threadStatus != 0) throw new IllegalThreadStateException(); //通知group该线程即将启动,group的未启动线程数量减1 group.add(this); boolean started = false; try { start0(); started = true; } finally { try { //启动不成功,group设置当前线程启动失败 if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { } }}
启动线程其实做了这么几件事:
- 检查线程是否初始化;
- 通知group,线程启动;
- 调用native方法start0()启动线程,启动后执行run()方法;
- 启动失败容错处理。
- 线程中断
中断可以理解为一个标识位的属性,它标识一个运行中的线程是否被其他线程进行了中断操作。
中断线程:
public void interrupt() { //中断其他线程,需要先判断当前线程是否允许修改其他线程 if (this != Thread.currentThread()) checkAccess(); //中断该线程 synchronized (blockerLock) { Interruptible b = blocker; if (b != null) { interrupt0();//设置中断标识位 b.interrupt(this); return; } } interrupt0();}
查看当前线程是否被中断:
public static boolean interrupted() { return currentThread().isInterrupted(true);}
查看线程是否被中断,已中断返回false
public boolean isInterrupted() { return isInterrupted(false);}
- 线程的暂停、恢复和停止
注: 这几个操作都加有@Deprecated注解,不推荐程序员使用
暂停:
//可能会造成死锁@Deprecatedpublic final void suspend() { checkAccess(); suspend0();}
恢复:
//可能会造成死锁@Deprecatedpublic final void resume() { checkAccess(); resume0();}
停止:
@Deprecatedpublic final synchronized void stop(Throwable obj) { if (obj == null) throw new NullPointerException(); SecurityManager security = System.getSecurityManager(); if (security != null) { checkAccess(); if ((this != Thread.currentThread()) || (!(obj instanceof ThreadDeath))) { security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION); } } //线程还未初始化好,暂停该线程 if (threadStatus != 0) { resume(); } //jvm处理线程相关内容 stop0(obj);}
- 线程优先级设置
public final void setPriority(int newPriority) { ThreadGroup g; checkAccess(); if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) { throw new IllegalArgumentException(); } if((g = getThreadGroup()) != null) { if (newPriority > g.getMaxPriority()) { newPriority = g.getMaxPriority(); } setPriority0(priority = newPriority); }}
需要注意的是:线程优先级不能作为程序正确性的依赖,操作系统有线程优先级的设定,不以程序设定的优先级为准!
后记
到这里位置,Thread的源码分析基本上就结束了,创建线程当然还可以实现Runnable接口方式来完成。后续文章将会继续给出current包下相关源码分析。
0 0
- Thread源码解析
- Java Thread 源码解析
- java thread join 源码解析
- JDK8中Thread源码解析
- bind源码解析(socket,thread)
- LK源码解析 3 thread.c
- Thread源码
- Thread类(Java多线程操作之Thread类,源码解析)
- MTK lk源码解析3( lk 阶段thread.c解析)
- 基于rt-thread+lwip源码分析-LWIP的IP层数据处理代码解析(lwip源码解析二)
- 通过JDK源码解析Thread(Runable target ...)调用的是哪个run方法
- ThreadLocal源码解析,以及ThreadLocal、ThreadLocalMap、Thread 三者之间的关系
- 通过JDK源码解析Thread(Runable target ...)调用的是哪个run方法
- chrome源码之thread
- Java Thread源码分析
- java Thread 源码分析
- java Thread源码分析
- Java Thread 源码 附录
- YUV格式分析
- Ubuntu 安装 JDK 7 / JDK8 的两种方式
- bug--Note: further occurrences of Cookie errors will be logged at DEBUG level.
- 开灯问题
- 学习笔记之JavaSE(54)--Java高级特性1
- Thread源码解析
- word mac for 2016 目录底部和图片的颜色变成了灰色如何恢复
- python基础知识点
- PHP过滤所有特殊字符的函数
- 微信web开发者工具中更改页面文件夹名称的正确姿势
- java日常笔记2016-12-07
- opencv灰度直方图统计
- Application类
- Android IPC机制