并发编程(一)-Thread 源码分析
创始人
2025-05-30 13:35:25
0

一、什么是线程


线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。

二、线程创建方式


2.1 继承Thread

public class MyThread extends Thread{@Overridepublic void run(){}
}

2.2 实现Runnable接口

public class MyThread implements Runnable(){@Overridepublic void run(){}
}

2.3 实现Callable接口

public class MyThread implements Callable {@Overridepublic Integer call() throws Exception {return 0;}
}

从Diagrams 图中就可得知,不管是extends Thread 还是 implements Callable接口,底层归根到底还是,实现了Runnable接口。

三、源码分析


3.1 线程中属性含义


// 线程名称
private volatile String name;
// 线程优先级
private int            priority;
// 内置的Thread类
private Thread         threadQ;
// JVM中的java thread 指针
private long           eetop;// 是否是单步执行此线程
private boolean     single_step;// 是否是守护线程
private boolean     daemon = false;// jvm 状态
private boolean     stillborn = false;// 构造函数中会传入的线程对象
private Runnable target;// 线程组
private ThreadGroup group;// 类加载器
private ClassLoader contextClassLoader;// 继承的访问下文
private AccessControlContext inheritedAccessControlContext;// 静态变量,使用内部静态类的单例模式,全局存在,用来生成线程名
private static int threadInitNumber;
private static synchronized int nextThreadNum() {return threadInitNumber++;
}// ThreadLocal 能为线程设置线程私有变量,设置线程上下文
ThreadLocal.ThreadLocalMap threadLocals = null;// inheritableThreadLocals 解决子线程能够获取父线程变量
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;// 给线程分配的栈大小,线程默认栈大小为0
private long stackSize;// 本地线程终止之后的专用状态
private long nativeParkEventPointer;// 线程id
private long tid;// 用于生成线程id,新创建线程后自增
private static long threadSeqNumber;// 线程状态,初始线程状态:0
private volatile int threadStatus = 0;// 生成线程id方法
private static synchronized long nextThreadID() {return ++threadSeqNumber;
}// LockSupport 中断
volatile Object parkBlocker;// interrupt 相关
private volatile Interruptible blocker;
private final Object blockerLock = new Object();
void blockedOn(Interruptible b) {synchronized (blockerLock) {blocker = b;}
}// 线程最低优先级
public final static int MIN_PRIORITY = 1;// 线程默认优先级
public final static int NORM_PRIORITY = 5;// 线程最高优先级
public final static int MAX_PRIORITY = 10;

3.2 线程状态

public enum State {// 新建状态:Thread t = new Thread();NEW,// 运行,调用了t.start(),此时就绪(等待CPU进行调度)和运行都属于运行状态。RUNNABLE,// 阻塞,因为争用 synchronized 的 monitor 对象而发生阻塞的线程处于 blocked 状态。BLOCKED,// 等待,需要其他的线程进行唤醒。一般是调用Object.wait,Thread.join,LockSupport.parkWAITING。可以调用Object.notify,Object.notifyAll,LockSupport.unpark进行唤醒// 超时等待,可以在指定时间内自动唤醒。调用Thread.sleep(long),Object.wait(long),Thread.join(long),// LockSupport.parkNanos(long),LockSupport.parkUntil(long)等进入TIMED_WAITING状态。// 唤醒方式:时间到了,Object.notify,Object.notifyAll,LockSupport.unpark等方法TIMED_WAITING,// 终止线程的线程状态。线程已完成执行。TERMINATED;
}

3.3构造方法

3.3.1 jdk1.8中Thread

3.4 init方法


private void init(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc,boolean inheritThreadLocals) {// 线程名称校验if (name == null) {throw new NullPointerException("name cannot be null");}this.name = name;// 父线程Thread parent = currentThread();// 获取安全管理器SecurityManager security = System.getSecurityManager();// 线程组为nullif (g == null) {// 安全管理器不为null,从安全管理器中获取线程组if (security != null) {g = security.getThreadGroup();}// 线程组为null,则从父线程中获取线程组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);if (inheritThreadLocals && parent.inheritableThreadLocals != null)// 子线程集成父线程的ThreadLocalthis.inheritableThreadLocals =ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);// 设置线程栈大小this.stackSize = stackSize;// 设置线程idtid = nextThreadID();
}

3.5 start方法

public synchronized void start() {// 检查线程状态是否是初始化状态( 0 == NEW)if (threadStatus != 0)throw new IllegalThreadStateException();// 线程组中添加该线程group.add(this);boolean started = false;try {// 调用native方法start0();// 成功启动标识started = true;} finally {try {// 没有启动成功if (!started) {// 从线程组中移除启动失败的线程group.threadStartFailed(this);}} catch (Throwable ignore) {}}
}private native void start0()

3.6 run方法


public void run() {if (target != null) {// 调用构造函数Runnable的run方法target.run();}
}

3.7 interrupt方法

interrupt并不是强制中断停止线程,仅仅更改线程状态。被设置中断标志的线程将继续正常运行,不受影响。


public void interrupt() {if (this != Thread.currentThread())checkAccess();synchronized (blockerLock) {Interruptible b = blocker;if (b != null) {// 设置中断状态interrupt0();         // 调用阻断程序中的中断方法b.interrupt(this);return;}}interrupt0();
}

3.8 enumerate方法

// 将当前线程组及其子线程组的线程复制到指定数组中
public static int enumerate(Thread tarray[]) {return currentThread().getThreadGroup().enumerate(tarray);
}

3.9 join(long 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");}// 等待毫秒数等于0,会一直等待,直到线程死亡,原理就是自旋等待if (millis == 0) {while (isAlive()) {wait(0);}} else {// 等待毫秒数大于0,超出等待时间,则退出。超时自旋等待while (isAlive()) {long delay = millis - now;// 如果等待时间小于等于0,退出等待if (delay <= 0) {break;}// 调用wait方法进行线程等待wait(delay);now = System.currentTimeMillis() - base;}}
}

3.10 sleep(long millis, int nanos)方法

线程休眠,线程休眠会将线程的cpu释放,但是线程占有的锁不会释放,当前线程进入Timed_waiting。

public static void sleep(long millis, int nanos)throws InterruptedException {// 睡眠毫秒实际小于0,抛出异常if (millis < 0) {throw new IllegalArgumentException("timeout value is negative");}// 睡眠纳秒时间 0~999999,if (nanos < 0 || nanos > 999999) {throw new IllegalArgumentException("nanosecond timeout value out of range");}// 1毫秒 = 1000000纳秒,纳秒数据超过一般0.5毫秒数据,就当做1毫秒,或者毫秒是0 而毫秒非零,也加1if (nanos >= 500000 || (nanos != 0 && millis == 0)) {millis++;}// 调用native方法,线程休眠sleep(millis);
}

3.11 yield方法

yield是 Thread 类中的native方法,作用:让出当前线程CPU的时间片,使当前线程从执行状态变为就绪状态,cpu将会从就绪队列中重新选择一个线程,也就是说,当前线程还是有可能会被再次选择的。

相关内容

热门资讯

武汉摩尔影城安卓系统APP,便... 你有没有想过,一部手机就能带你走进电影的世界,享受大屏幕带来的震撼?今天,就让我带你详细了解武汉摩尔...
联想刷安卓p系统,畅享智能新体... 你有没有发现,最近联想的安卓P系统刷机热潮可是席卷了整个互联网圈呢!这不,我就迫不及待地来和你聊聊这...
mac从安卓系统改成双系统,双... 你有没有想过,你的Mac电脑从安卓系统改成双系统后,生活会有哪些翻天覆地的变化呢?想象一边是流畅的苹...
kindke安卓系统激活码,激... 亲爱的读者,你是否在寻找一款能够让你手机焕然一新的操作系统?如果你是安卓用户,那么今天我要给你带来一...
萤石云监控安卓系统,安卓系统下... 你有没有想过,家里的安全可以随时随地掌握在手中?现在,有了萤石云监控安卓系统,这不再是梦想啦!想象无...
手机安卓系统会不会爆炸,系统升... 手机安卓系统会不会爆炸——一场关于安全的探讨在当今这个数字化的世界里,手机已经成为我们生活中不可或缺...
安卓系统双清详图解,恢复出厂设... 你有没有遇到过手机卡顿、运行缓慢的问题?别急,今天就来给你详细解析一下安卓系统的“双清”操作,让你的...
召唤抽奖系统安卓直装,轻松体验... 你知道吗?现在市面上有一种特别火的玩意儿,那就是召唤抽奖系统安卓直装。是不是听起来就让人心动不已?没...
系统工具箱安卓2.3,深度解析... 你有没有发现,手机里的那些小工具,有时候就像是个神奇的百宝箱呢?今天,就让我带你一探究竟,看看安卓2...
华硕平板安卓刷机系统,解锁性能... 亲爱的数码爱好者们,你是否曾为你的华硕平板安卓系统感到厌倦,想要给它来一次焕然一新的体验呢?那就跟着...
鸿蒙系统与安卓怎么区别,差异解... 你有没有发现,最近手机圈子里有个大热门,那就是鸿蒙系统和安卓系统的区别。这两位“系统大侠”各有各的绝...
红帽系统怎么刷回安卓,红帽系统... 你是不是也和我一样,对红帽系统刷回安卓充满了好奇?别急,今天就来给你详细揭秘这个过程,让你轻松上手,...
ios安卓联想三系统,全面解析... 你有没有发现,现在的手机市场真是热闹非凡呢!各种操作系统轮番登场,让人眼花缭乱。今天,就让我带你来聊...
安卓调用系统相机并存盘,And... 你有没有想过,手机里的照片和视频,是怎么被我们随手拍下,又神奇地存到手机里的呢?今天,就让我带你一探...
安卓4.0原生系统下,引领智能... 你有没有发现,安卓4.0原生系统下,手机的使用体验简直就像打开了新世界的大门?今天,就让我带你一起探...
安卓c13系统,创新功能与性能... 你知道吗?最近安卓系统又来了一次大更新,那就是安卓C13系统。这可不是一个小打小闹的更新,而是带来了...
鸿蒙3.0脱离安卓系统,开启全... 你知道吗?最近科技圈可是炸开了锅,因为华为的新操作系统鸿蒙3.0横空出世,竟然宣布要脱离安卓系统,这...
安卓怎么应对苹果系统,安卓系统... 你知道吗?在智能手机的世界里,安卓和苹果就像是一对相爱相杀的恋人。安卓系统,这位多才多艺的“大众情人...
安卓系统如何开橱窗教程,安卓系... 你有没有想过,你的安卓手机里也能开个橱窗,展示那些你心爱的宝贝?没错,就是那种可以随时翻看、随时分享...
安卓系统软件APK,深入探究安... 你有没有发现,手机里的那些好玩的应用,其实都是靠一个小小的文件来“住”进去的?没错,就是安卓系统里的...