总结与使用

1.线程状态

1.extends 和 implement

a.Thread 类实现了Runnable接口

  1. @Override
  2. public void run() {
  3. if (target != null) {
  4. target.run(); // target Thread 类的属性, Runnable target;
  5. }
  6. }

2.构造方法

a. Thread()
b. Thread(Runnable target)
c. protected Thread(Runnable target, AccessControlContext acc)
……

  1. public Thread() {init(null, null, "Thread-" + nextThreadNum(), 0);}
  2. public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); }
  3. public Thread(Runnable target, String name){init(null, target, name, 0);};
  4. public Thread(String name) {init(null, null, name, 0); }
  5. protected Thread(Runnable target, AccessControlContext acc) {init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);}
  6. public Thread(ThreadGroup group, Runnable target) {init(group, target, "Thread-" + nextThreadNum(), 0);}
  7. public Thread(ThreadGroup group, Runnable target, String name) {init(group, target, name, 0);}
  8. public Thread(ThreadGroup group, Runnable target, String name,long stackSize) {init(group, target, name, stackSize);}
  9. public Thread(ThreadGroup group, String name) {init(group, null, name, 0);}
  1. 构造方法中,综合起来总共ThreadGroupThreadNameRunnableStatckSizeAccessControlContext,调用初始化方法 【[init](https://www.yuque.com/ekci59/cbvivg/cigauh#tXANs)】 初始化线程的属性。

3.属性

【name】:线程名, volatile ,线程外可见,

【priority】: 优先级

【daemon】 :线程是否守护线程

【contextClassLoader】:线程上下文类加载器

【uncaughtExceptionHandler】:线程异常未捕获,突然中止调用的Handler未设置时为null

【defaultUncaughtExceptionHandler】:线程突然终止,默认的Handler

【tid】:线程id

【inheritedAccessControlContext】:线程上下文系统资源访问决策,checkPermisssion,继承的快照

【target】:线程执行目标

【statckSize】:线程占用栈大小

【threadStatus】:线程状态,初始化为0,表示未启动

【eetop】: 未查询到使用

【single_step】:是否单步执行此线程

【stillborn】:JVM 状态

【group】:线程所属的组

【threadInitNumber】:线程编号,构造方法调用nextThreadNum(),每次创建线程这个值++

【threadLocals】:线程本地变量

【inheritableThreadLocals】:从构造线程继承的线程本地变量

【nativeParkEventPointer】:JVM私用状态,本机线程结束后依然存在

【threadSeqNumber】:线程序列号,用于生成线程id

【blocker】: Interruptible类,这个对象通过可中断的I/O操作阻塞线程,设置线程中断后,调用阻塞程序的interrupt方法。

【blockerLock】:调用阻塞操作时锁对象

【parkBlocker】:通过LockSupport对线程挂起和恢复,parkBlocker专为LockSupport而设计,用来记录线程堵塞对象,设置好parkBlocker值后,线程挂起,线程恢复后,parkBlocker设置为null。

  1. private volatile String name;
  2. private int priority;
  3. private boolean daemon = false;
  4. private ClassLoader contextClassLoader;
  5. private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
  6. private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
  7. private long tid;
  8. private AccessControlContext inheritedAccessControlContext;
  9. private Runnable target;
  10. private long stackSize;
  11. private volatile int threadStatus = 0;
  12. private long eetop;
  13. private boolean single_step;
  14. private boolean stillborn = false;
  15. private ThreadGroup group;
  16. private static int threadInitNumber;
  17. ThreadLocal.ThreadLocalMap threadLocals = null;
  18. ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
  19. private long nativeParkEventPointer;
  20. private static long threadSeqNumber;
  21. private volatile Interruptible blocker;
  22. private final Object blockerLock = new Object();
  23. volatile Object parkBlocker;

关于volatile,volatile 声明的对象,线程外可见,但是多个线程修改volatile值时,同样会出现问题,volatile确保的是可见性,但是写操作仍然是不安全的。详细可以了解volatile在内存中的处理方式。

4.方法

Native方法

registerNatives() : 静态块调用,确保在【cinit】前加载,让JVM能够发现native function,通过这个方法,能够随意命名C函数。

currentThread():返回当前正在执行的线程对象的引用

yield():通知调度线程,当前线程愿意放弃当前使用的处理器,通常作为测试使用

setPriority0(int newPriority):设置新的优先级

sleep(long millis):线程休眠,线程休眠会将现场从cpu释放,但是线程占有的锁不会释放

stop0(Object o):线程停止

resume0():恢复被挂起的线程

interrupt0():线程中断方法,设置中断标志

isInterrupted(boolean ClearInterrupted):线程是否中断

holdsLock(Object obj): 判断线程在指定对象上,是否持有监视器锁

suspend0: 线程挂起

Java方法

【init】:

参数:
ThreadGroup 线程所属线程组
Runnable 线程运行
name 线程名
stackSize 初生线程栈大小,0表示忽略
AccessControlContext 用于应该在给定上下文中进行检查,实际上需要在不同上下文中进行(Thread就是典型)
inheritThreadLocals:如果为true ,从构造线程 继承 可继承的线程局部变量的初始值
通过init方法初始化的属性:【name】【group】【daemon】【priority】【contextClassLoader】【inheritedAccessControlContext】【inheritableThreadLocals】【stackSize】【id】

  1. private void init(ThreadGroup g, Runnable target, String name,long stackSize) {init(g, target, name, stackSize, null, true);}
  2. private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc,boolean inheritThreadLocals) {
  3. //线程名不允许为空,未定义名称的构造方法Java会给定一个默认的名称
  4. if (name == null) {
  5. throw new NullPointerException("name cannot be null");
  6. }
  7. this.name = name;
  8. Thread parent = currentThread();//当前正在执行的线程,这个线程作为父线程
  9. SecurityManager security = System.getSecurityManager();//安全管理器
  10. if (g == null) {//如果线程组参数为空,那么需要获取到先创建的线程的线程组
  11. if (security != null) {//如果当前应用程序已经开启了安全管理器,那么通过安全管理器获取线程组,可通过配置-Djava.security.manager开启,相关安全管理器知识,有兴趣可以自行查看
  12. g = security.getThreadGroup();
  13. }
  14. if (g == null) {//如果安全管理器未开启,那么就从父线程中获取线程组
  15. g = parent.getThreadGroup();
  16. }
  17. }
  18. //确定当前线程是否有修改线程组的权限,如果安全管理器开启,会进行检查,如果未开启,那么不会检查
  19. g.checkAccess();
  20. //安全管理器开启情况下
  21. if (security != null) {
  22. if (isCCLOverridden(getClass())) {//如果子类方法覆盖了,那么需要进行权限检查,如果安全策略不通过权限检查,那么异常抛出AccessControlException。
  23. security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
  24. }
  25. }
  26. //增加线程组中未启动线程的计数 Group:nUnstartedThreads++;
  27. g.addUnstarted();
  28. //设置线程的相关属性
  29. this.group = g;
  30. this.daemon = parent.isDaemon();
  31. this.priority = parent.getPriority();
  32. //TODO 看方法代码 当security ==null 时, this.contextClassLoader = parent.getContextClassLoader() 与 this.contextClassLoader = parent.contextClassLoader 效果一样?
  33. if (security == null || isCCLOverridden(parent.getClass()))
  34. this.contextClassLoader = parent.getContextClassLoader();
  35. else
  36. this.contextClassLoader = parent.contextClassLoader;
  37. //如果没有传入了acc ,那么获取当前上下文的快照
  38. this.inheritedAccessControlContext = acc != null ? acc : AccessController.getContext();
  39. //Runnable
  40. this.target = target;
  41. //线程组内优先级
  42. setPriority(priority);
  43. //如果可以继承构造线程的本地变量值
  44. if (inheritThreadLocals && parent.inheritableThreadLocals != null)
  45. this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
  46. //线程初始化栈大小,未指定,则设置为0
  47. this.stackSize = stackSize;
  48. //设置线程id
  49. tid = nextThreadID();
  50. }

【start】

开始执行线程,虚拟机会调用该线程的run方法。

  1. public synchronized void start() {
  2. //线程如果已经启动,那么抛出异常,同一线程不能启动两次
  3. if (threadStatus != 0)
  4. throw new IllegalThreadStateException();
  5. //添加线程到线程组
  6. group.add(this);
  7. boolean started = false;
  8. try {
  9. //执行native方法
  10. start0();
  11. //没有异常,线程执行成功
  12. started = true;
  13. } finally {
  14. try {
  15. if (!started) {
  16. //如果执行失败了,那么去除组内的这个线程
  17. group.threadStartFailed(this);
  18. }
  19. } catch (Throwable ignore) {
  20. }
  21. }
  22. }

【run】

执行线程,如果线程是实现Runnable的类,那么不会执行这个run方法。不然就会执行这个方法。

  1. @Override
  2. public void run() {
  3. if (target != null) {
  4. target.run();
  5. }
  6. }

【exit】

线程实际退出时,清理线程数据,这个方法是由系统来调用

  1. private void exit() {
  2. if (group != null) {
  3. //线程组中清理线程
  4. group.threadTerminated(this);
  5. //当前线程的线程组引用设置成null
  6. group = null;
  7. }
  8. //当前线程相关的属性设置null
  9. target = null;
  10. threadLocals = null;
  11. inheritableThreadLocals = null;
  12. inheritedAccessControlContext = null;
  13. blocker = null;
  14. uncaughtExceptionHandler = null;
  15. }

【stop】

线程停止方法,@Deprecated,已被弃用
如果线程已经启动,那么将立即终止。 线程停止会解锁所有已经锁定的监视器,这种终止的操作很不安全。

  1. public final void stop() {
  2. //安全检查
  3. SecurityManager security = System.getSecurityManager();
  4. if (security != null) {
  5. checkAccess();
  6. if (this != Thread.currentThread()) {
  7. security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
  8. }
  9. }
  10. //如果线程状态不是新建,并且线程被挂起,那么将恢复该线程,否则不处理
  11. if (threadStatus != 0) {
  12. resume();
  13. }
  14. //停止线程
  15. stop0(new ThreadDeath());
  16. }

【interrupt】

线程中断,

  1. public void interrupt() {
  2. if (this != Thread.currentThread())
  3. checkAccess();
  4. synchronized (blockerLock) {
  5. Interruptible b = blocker;
  6. if (b != null) {
  7. //设置中断状态
  8. interrupt0();
  9. //调用阻断程序中的中断方法
  10. b.interrupt(this);
  11. return;
  12. }
  13. }
  14. interrupt0();
  15. }

【interrupted】

当前线程是否被中断

【isCCLOverridden】

验证,是否满足安全约束,子类不得覆盖安全性敏感的non-final方法

  1. private static boolean isCCLOverridden(Class<?> cl) {
  2. if (cl == Thread.class)
  3. return false;
  4. //移除子类安全检查结果队列顶部缓存
  5. processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
  6. //创建一个弱键
  7. WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
  8. 缓存中是否有该键对应的对象,如果有,则取出
  9. Boolean result = Caches.subclassAudits.get(key);
  10. if (result == null) {
  11. //安全检查
  12. result = Boolean.valueOf(auditSubclass(cl));
  13. //检查结果存入缓存
  14. Caches.subclassAudits.putIfAbsent(key, result);
  15. }
  16. return result.booleanValue();
  17. }

【processQueue】

如果队列不为空,移除队列头部元素,并将头部元素map中映射也移除

  1. static void processQueue(ReferenceQueue<Class<?>> queue,ConcurrentMap<? extends WeakReference<Class<?>>, ?> map){
  2. Reference<? extends Class<?>> ref;
  3. while((ref = queue.poll()) != null) {
  4. map.remove(ref);
  5. }
  6. }

【auditSubclass】

子类安全检查方法,通过反射进行检查,线上上下文加载器的方法 getContextClassLoader,setContextClassLoader,确保不被覆盖

  1. private static boolean auditSubclass(final Class<?> subcl) {
  2. Boolean result = AccessController.doPrivileged(
  3. new PrivilegedAction<Boolean>() {
  4. public Boolean run() {
  5. //向上查找父类,直到Thread终止
  6. for (Class<?> cl = subcl; cl != Thread.class; cl = cl.getSuperclass()) {
  7. try {
  8. //如果查询到了方法,返回return,未查询到,异常捕获,不做处理
  9. cl.getDeclaredMethod("getContextClassLoader", new Class<?>[0]);
  10. return Boolean.TRUE;
  11. } catch (NoSuchMethodException ex) {}
  12. try {
  13. Class<?>[] params = {ClassLoader.class};
  14. cl.getDeclaredMethod("setContextClassLoader", params);
  15. return Boolean.TRUE;
  16. } catch (NoSuchMethodException ex) {}
  17. }
  18. return Boolean.FALSE;
  19. }
  20. }
  21. );
  22. return result.booleanValue();
  23. }

【getContextClassLoader】

获取线程上下文ClassLoader

  1. @CallerSensitive
  2. public ClassLoader getContextClassLoader() {
  3. if (contextClassLoader == null)
  4. return null;
  5. SecurityManager sm = System.getSecurityManager();
  6. if (sm != null) {
  7. //如果调用者的类加载器不为空且调用者的类加载器与给定的class参数的祖先不同,那么检查RuntimePermission("getClassLoader")权限
  8. ClassLoader.checkClassLoaderPermission(contextClassLoader,Reflection.getCallerClass());
  9. }
  10. return contextClassLoader;
  11. }

【setPriority】

设置优先级,线程组内

  1. public final void setPriority(int newPriority) {
  2. ThreadGroup g;
  3. checkAccess();
  4. if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
  5. throw new IllegalArgumentException();
  6. }
  7. if((g = getThreadGroup()) != null) {
  8. if (newPriority > g.getMaxPriority()) {
  9. newPriority = g.getMaxPriority();
  10. }
  11. setPriority0(priority = newPriority);
  12. }
  13. }

【destroy】@Deprecated

销毁线程

【suspend】@Deprecated

线程挂起

【resume】@Deprecated

线程恢复被挂起的线程

【activeCount】

当前线程组(包括子组)中活跃的线程数,递归统计

  1. public static int activeCount() {
  2. return currentThread().getThreadGroup().activeCount();
  3. }

【enumerate】

将当前线程组及其子组的线程复制到指定数组中

  1. public static int enumerate(Thread tarray[]) {
  2. return currentThread().getThreadGroup().enumerate(tarray);
  3. }

【join】

主线程等待子线程执行,Object.wait(), 必须等待对该对象notify,notifyAll 或者超过了等待时间才会释放

  1. public final synchronized void join(long millis) throws InterruptedException {
  2. long base = System.currentTimeMillis();
  3. long now = 0;
  4. if (millis < 0) {
  5. throw new IllegalArgumentException("timeout value is negative");
  6. }
  7. if (millis == 0) {
  8. //如果毫秒数等于0,会一直等待,直到线程死亡
  9. while (isAlive()) {
  10. wait(0);
  11. }
  12. } else {
  13. //如果毫秒数不等于0,超出毫秒数之后会退出等待
  14. while (isAlive()) {
  15. long delay = millis - now;
  16. if (delay <= 0) {break;}
  17. wait(delay);
  18. now = System.currentTimeMillis() - base;
  19. }
  20. }
  21. }

【dumpStack】

将线程堆栈信息打印,仅用于dubgger

【checkAccess】

安全检查

5.内部类

静态内部类

【Caches】 private static class

缓存子类安全审核结果

  1. private static class Caches {
  2. //子类安全结果审核的缓存
  3. static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits = new ConcurrentHashMap<>();
  4. //已审计子类弱引用队列
  5. static final ReferenceQueue<Class<?>> subclassAuditsQueue = new ReferenceQueue<>();
  6. }

【WeakClassKey】

类对象的弱键类,继承了弱引用类
题外话:Java 引用类型,强引用,软引用,弱引用,虚引用 ,不了解可以查询一下资料。

  1. static class WeakClassKey extends WeakReference<Class<?>> {
  2. private final int hash;
  3. //构造方法 父类构造,创建一个弱引用,并且放入给定的队列当中,然后设置一个hash值,indentityHashCode只有当引用对象相同时hashcode相同
  4. WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {
  5. super(cl, refQueue);
  6. hash = System.identityHashCode(cl);
  7. }
  8. @Override
  9. public int hashCode() {
  10. return hash;
  11. }
  12. @Override
  13. public boolean equals(Object obj) {
  14. if (obj == this)
  15. return true;
  16. if (obj instanceof WeakClassKey) {
  17. Object referent = get();
  18. return (referent != null) &&
  19. (referent == ((WeakClassKey) obj).get());
  20. } else {
  21. return false;
  22. }
  23. }
  24. }

枚举类

【State】 线程状态类

  1. public enum State {
  2. //新建状态,调用了init方法,未调用run
  3. NEW,
  4. //运行中,正在虚拟机中执行,如果在等待操作系统分配资源,也是运行中的状态
  5. RUNNABLE,
  6. //阻塞状态,等待监视器锁定。
  7. BLOCKED,
  8. //线程等待 Thread.join()/Object.wait() 未指定超时时间,LockSupport.park() 。等待另一个线程 执行 Object.notify/notifyAll ,LockSupprot.unpark。
  9. WAITING,
  10. //限时等待 Thread.join(timeout) /Object.wait(timeout) Thread.sleep(timeout)指定超时时间,LockSupport.parkNanos()/parkUntil()。 Object.notify/notifyAll 或者超时,状态结束。
  11. TIMED_WAITING,
  12. //线程终止
  13. TERMINATED;
  14. }