Thread实现Runnable接口

1.Thread内部有个State枚举,标示着线程的状态。

  • NEW,新建未开始
  • RUNNABLE,可执行
  • BLOCKED,阻塞状态,等待一个monitor lock,或者Object.wait()之后重入一个synchronized锁定的代码
  • WAITING,等待状态,Object.wait(),Thread.join(),LockSupport.park()之后进入此状态
  • TIMED_WAITING,带超时时间的等待状态,Object.wait(long),Thread.join(long),LockSupport.parkNanos(),LockSupport.parkUntil()之后进入此状态
  • TERMINATED,终止状态

2.接着看下Thread的构造函数及其几个相关的成员变量

/* 带目标run对象. */private Runnable target;/* 线程组 */private ThreadGroup group;/* 此线程的类加载器 */private ClassLoader contextClassLoader;/* 想要的栈大小,为0时此参数被忽略,且有VM不支持此参数 */private long stackSize;/* 状态标识,0代表新建未开始*/private volatile int threadStatus = 0;/* 静态native方法,返回当前线程*/public static native Thread currentThread();public Thread() {init(null, null, "Thread-" + nextThreadNum(), 0);}public Thread(Runnable target) {init(null, target, "Thread-" + nextThreadNum(), 0);}Thread(Runnable target, AccessControlContext acc) {init(null, target, "Thread-" + nextThreadNum(), 0, acc);}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);}/*** Initializes a Thread.** @param g 线程组* @param target 要执行的带run的目标对象* @param name 线程名* @param stackSize 新线程的栈大小,等于0时可忽略此参数* @param acc 接入控制上下文*/private void init(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc) {if (name == null) {throw new NullPointerException("name cannot be null");}this.name = name;Thread parent = currentThread();SecurityManager security = System.getSecurityManager();//获取线程组if (g == null) {/* 从SecurityManager拿线程组  */if (security != null) {g = security.getThreadGroup();}/* 如果还没拿到从当前线程拿*/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();elsethis.contextClassLoader = parent.contextClassLoader;this.inheritedAccessControlContext =acc != null ? acc : AccessController.getContext();this.target = target;setPriority(priority);//从父线程继承可继承的ThreadLocalif (parent.inheritableThreadLocals != null)this.inheritableThreadLocals =ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);this.stackSize = stackSize;/* 设置线程ID */tid = nextThreadID();}

不同的构造函数很多,最终都调init方法,init主要实现的就是把相应的参数放入成员变量里,ThreadGroup的获取,接入控制,inheritableThreadLocals父继承,线程id自增。

3.调用线程执行的主方法start及run方法

/* 线程启动方法 */public synchronized void start() {/*** 如果线程不是NEW状态,则抛异常*/if (threadStatus != 0)throw new IllegalThreadStateException();/*通知线程组此线程准备运行里,所以它可以加入到线程组列表中,线程组的未开始数量可以减少了 */group.add(this);boolean started = false;try {start0();started = true;} finally {try {if (!started) {group.threadStartFailed(this);}} catch (Throwable ignore) {/*什么都不做,如果start0排除一个异常,它已经可以被调用栈知道 */}}}private native void start0();

start方法主要也是native实现,真正开始之前校验了状态,并接入ThreadGroup管理。

/* Runnale 接口的方法*/@Overridepublic void run() {if (target != null) {target.run();}}

真正的run其实是目标类的run方法

4.join方法,等待线程挂掉的方法,会抛出InterruptedException

/*如果这个线程还活着就一直等待*/public final void join() throws InterruptedException {join(0);}
/*如果这个线程还活着就一直等待millis时间*/
public final synchronized void join(long millis)throws InterruptedException {long base = System.currentTimeMillis();long now = 0;if (millis < 0) {throw new IllegalArgumentException("timeout value is negative");}if (millis == 0) {while (isAlive()) {wait(0);}} else {while (isAlive()) {long delay = millis - now;if (delay <= 0) {break;}wait(delay);now = System.currentTimeMillis() - base;}}}

Thread里为数不多的纯Java代码,它被synchronized标记,实现主要是自旋方法检验线程是否活着,如果活着,则wait释放锁,还有疑问请移步join的讨论

6.sleep方法,native实现,会抛出InterruptedException

/* 睡眠指定毫秒,并不释放monitor*/public static native void sleep(long millis) throws InterruptedException;

7.yield方法,native实现

/*使当前线程从执行状态(运行状态)变为可执行态(就绪状态)。cpu会从众多的可执行态里选择,也就是说,当前也就是刚刚的那个线程还是有可能会被再次执行到的,并不是说一定会执行其他线程而该线程在下一次中不会执行到了*/public static native void yield();

7.interrupt方法,更多关于中断的请见处理中断

每个线程都有一个与之相关联的 Boolean 属性,用于表示线程的中断状态(interrupted status)。中断状态初始时为 false;当另一个线程通过调用 Thread.interrupt() 中断一个线程时,会出现以下两种情况之一。如果那个线程在执行一个低级可中断阻塞方法,例如 Thread.sleep()、 Thread.join() 或 Object.wait(),那么它将取消阻塞并抛出 InterruptedException。否则, interrupt() 只是设置线程的中断状态。 在被中断线程中运行的代码以后可以轮询中断状态,看看它是否被请求停止正在做的事情。中断状态可以通过 Thread.isInterrupted() 来读取,并且可以通过一个名为 Thread.interrupted() 的操作读取和清除。
中断是一种协作机制。当一个线程中断另一个线程时,被中断的线程不一定要立即停止正在做的事情。相反,中断是礼貌地请求另一个线程在它愿意并且方便的时候停止它正在做的事情。有些方法,例如 Thread.sleep(),很认真地对待这样的请求,但每个方法不是一定要对中断作出响应。对于中断请求,不阻塞但是仍然要花较长时间执行的方法可以轮询中断状态,并在被中断的时候提前返回。 您可以随意忽略中断请求,但是这样做的话会影响响应。
中断的协作特性所带来的一个好处是,它为安全地构造可取消活动提供更大的灵活性。我们很少希望一个活动立即停止;如果活动在正在进行更新的时候被取消,那么程序数据结构可能处于不一致状态。中断允许一个可取消活动来清理正在进行的工作,恢复不变量,通知其他活动它要被取消,然后才终止。

/* * 这个对象的线程被可中断的I/O操作阻塞,这个blocker的interrupt方法应      * 该被设置完中断状态后触发*/private volatile Interruptible blocker;private final Object blockerLock = new Object();/* 设置blocker; invoked via sun.misc.SharedSecrets from java.nio code*/void blockedOn(Interruptible b) {synchronized (blockerLock) {blocker = b;}}public void interrupt() {if (this != Thread.currentThread())checkAccess();synchronized (blockerLock) {//如果被可中断IO阻塞,走此逻辑Interruptible b = blocker;if (b != null) {interrupt0();           // 仅仅设置interrupt标识位b.interrupt(this);     return;}}interrupt0();}//当前线程是否被中断,并清空中断状态(连续两次调用,第二次一定返回false)public static boolean interrupted() {return currentThread().isInterrupted(true);}//当前线程是否被中,根据true,false来是否重置中断zhuangtprivate native boolean isInterrupted(boolean ClearInterrupted);//当前线程是否被中断,不修改中断状态public boolean isInterrupted() {return isInterrupted(false);} 

其它还有很多调试的方法activeCount,dumpStack就不讨论了

Thread源码阅读相关推荐

  1. mysql thread conn_MySQL源码阅读2-连接与线程管理

    本篇是第二篇,MySQL初始化完成之后,便进入一个死循环中,接受客户端请求,并完成客户端的命令(如果在window下启动多个listener,则分别启动线程监听).该篇介绍MySQL服务中的连接与线程 ...

  2. 应用监控CAT之cat-client源码阅读(一)

    CAT 由大众点评开发的,基于 Java 的实时应用监控平台,包括实时应用监控,业务监控.对于及时发现线上问题非常有用.(不知道大家有没有在用) 应用自然是最初级的,用完之后,还想了解下其背后的原理, ...

  3. 12.源码阅读(app启动流程-android api 26)

    activity的启动流程之前已经通过源码了解了,那么app的启动流程是怎样的,从我们按下app的图标,到应用启动起来显示出画面,中间都经历了什么? 安卓是基于java的,所以和java有一定的相似性 ...

  4. Java8 ArrayBlockingQueue 源码阅读

    一.什么是 ArrayBlockingQueue ArrayBlockingQueue 是 GUC(java.util.concurrent) 包下的一个线程安全的阻塞队列,底层使用数组实现. 除了线 ...

  5. 多线程与高并发(四):LockSupport,高频面试题,AQS源码,以及源码阅读方法论

    补充几道面试题 锁升级过程:无锁.偏向锁.轻量级锁.重量级锁 StampedLock 自己看一下 面试题:syn和Reentrantlock的区别? LockSupport LockSupport.p ...

  6. zookeeper 源码阅读(2)

    接着zookeeper 源码阅读(1) Zookeeper服务器的启动,大致可以分为以下五个步骤 1. 配置文件解析. 2. 初始化数据管理器. 3. 初始化网络I/O管理器. 4. 数据恢复. 5. ...

  7. surefire 拉起 junit 单元测试类 源码阅读(一)

    根据surefire 拉起Junit单元测试类 输出的报错日志 跟踪执行过程: 日志1: java.lang.reflect.InvocationTargetExceptionat sun.refle ...

  8. DotText源码阅读(7) --Pingback/TrackBack

    DotText源码阅读(7) --Pingback/TrackBack 博客这种服务的区别于论坛和所谓文集网站,很大程度上我认为是由于pingback/trackback的存在,使得博客这种自媒体有可 ...

  9. AQS源码阅读笔记(一)

    AQS源码阅读笔记 先看下这个类张非常重要的一个静态内部类Node.如下: static final class Node {//表示当前节点以共享模式等待锁static final Node SHA ...

最新文章

  1. Chrome OS与平板电脑才是珠联璧合
  2. android ffmegp for_FFmpeg 编译for Android
  3. ubuntu 开启关闭mysql 服务
  4. js 将图片置灰_JS 上传一张图片让其部分变灰色
  5. ajax回调打开新窗体防止浏览器拦截方法
  6. 马斯克扎心了!猎鹰重型火箭核心助推器运输过程中坠海
  7. 易语言超文本ctrl c,易语言超文本浏览框处理键盘消息源码
  8. 2012总结--目录
  9. 计算机网络-自顶向下方法(7th) 第一章 Review Questions 中英对照
  10. Atitit 编程语言编程方法的进化演进 sp  COP ,AOP ,SOP
  11. ai跟随路径_ai中图像怎么沿着路径走
  12. 二维码应用——门禁系统
  13. [Contrastive Learning] Improving Contrastive Learning by Visualizing Feature Transformation
  14. HTTP的options方法作用
  15. AR涂涂乐项目之识别图制作模型的制作一
  16. 3451. 易位构词
  17. Java获取Excel中链接的文件
  18. 【Java每日编程小练习 2021-01-21】 幸运手机号的简单产生
  19. PS5手柄可兼容安卓系统和win系统
  20. MATLAB画三维动态魔方/旋转魔方/旋转立方体

热门文章

  1. idea启动前端vue项目(各种坑)
  2. Cartographor定位-shell脚本:不停拉起死掉的程序和脚本
  3. libopencv_core.a(persistence.cpp.o): undefined reference to symbol 'gzclose'
  4. 多样化实现Windows Phone 7本地数据访问3——DB4O
  5. django 中 csrf问题 的解决方法
  6. Spark安装配置指南
  7. orcale的rank(排名函数)实例
  8. xml 文件解析 pull
  9. Xcode自定义字体不能应用的原因
  10. Centos 6.4搭建svnadmin服务器