- 总结与使用
- 1.extends 和 implement
- 2.构造方法
- 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。
- 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方法
- Native方法
- 5.内部类
总结与使用
1.线程状态
1.extends 和 implement
a.Thread 类实现了Runnable接口
@Overridepublic void run() {if (target != null) {target.run(); // target Thread 类的属性, Runnable target;}}
2.构造方法
a. Thread()
b. Thread(Runnable target)
c. protected Thread(Runnable target, AccessControlContext acc)
……
public Thread() {init(null, null, "Thread-" + nextThreadNum(), 0);}public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); }public Thread(Runnable target, String name){init(null, target, name, 0);};public Thread(String name) {init(null, null, name, 0); }protected Thread(Runnable target, AccessControlContext acc) {init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);}public Thread(ThreadGroup group, Runnable target) {init(group, target, "Thread-" + nextThreadNum(), 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);}public Thread(ThreadGroup group, String name) {init(group, null, name, 0);}
构造方法中,综合起来总共ThreadGroup,ThreadName,Runnable,StatckSize,AccessControlContext,调用初始化方法 【[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。
private volatile String name;private int priority;private boolean daemon = false;private ClassLoader contextClassLoader;private volatile UncaughtExceptionHandler uncaughtExceptionHandler;private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;private long tid;private AccessControlContext inheritedAccessControlContext;private Runnable target;private long stackSize;private volatile int threadStatus = 0;private long eetop;private boolean single_step;private boolean stillborn = false;private ThreadGroup group;private static int threadInitNumber;ThreadLocal.ThreadLocalMap threadLocals = null;ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;private long nativeParkEventPointer;private static long threadSeqNumber;private volatile Interruptible blocker;private final Object blockerLock = new Object();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】
private void init(ThreadGroup g, Runnable target, String name,long stackSize) {init(g, target, name, stackSize, null, true);}private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc,boolean inheritThreadLocals) {//线程名不允许为空,未定义名称的构造方法Java会给定一个默认的名称if (name == null) {throw new NullPointerException("name cannot be null");}this.name = name;Thread parent = currentThread();//当前正在执行的线程,这个线程作为父线程SecurityManager security = System.getSecurityManager();//安全管理器if (g == null) {//如果线程组参数为空,那么需要获取到先创建的线程的线程组if (security != null) {//如果当前应用程序已经开启了安全管理器,那么通过安全管理器获取线程组,可通过配置-Djava.security.manager开启,相关安全管理器知识,有兴趣可以自行查看g = security.getThreadGroup();}if (g == null) {//如果安全管理器未开启,那么就从父线程中获取线程组g = parent.getThreadGroup();}}//确定当前线程是否有修改线程组的权限,如果安全管理器开启,会进行检查,如果未开启,那么不会检查g.checkAccess();//安全管理器开启情况下if (security != null) {if (isCCLOverridden(getClass())) {//如果子类方法覆盖了,那么需要进行权限检查,如果安全策略不通过权限检查,那么异常抛出AccessControlException。security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);}}//增加线程组中未启动线程的计数 Group:nUnstartedThreads++;g.addUnstarted();//设置线程的相关属性this.group = g;this.daemon = parent.isDaemon();this.priority = parent.getPriority();//TODO 看方法代码 当security ==null 时, this.contextClassLoader = parent.getContextClassLoader() 与 this.contextClassLoader = parent.contextClassLoader 效果一样?if (security == null || isCCLOverridden(parent.getClass()))this.contextClassLoader = parent.getContextClassLoader();elsethis.contextClassLoader = parent.contextClassLoader;//如果没有传入了acc ,那么获取当前上下文的快照this.inheritedAccessControlContext = acc != null ? acc : AccessController.getContext();//Runnablethis.target = target;//线程组内优先级setPriority(priority);//如果可以继承构造线程的本地变量值if (inheritThreadLocals && parent.inheritableThreadLocals != null)this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);//线程初始化栈大小,未指定,则设置为0this.stackSize = stackSize;//设置线程idtid = nextThreadID();}
【start】
开始执行线程,虚拟机会调用该线程的run方法。
public synchronized void start() {//线程如果已经启动,那么抛出异常,同一线程不能启动两次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) {}}}
【run】
执行线程,如果线程是实现Runnable的类,那么不会执行这个run方法。不然就会执行这个方法。
@Overridepublic void run() {if (target != null) {target.run();}}
【exit】
线程实际退出时,清理线程数据,这个方法是由系统来调用
private void exit() {if (group != null) {//线程组中清理线程group.threadTerminated(this);//当前线程的线程组引用设置成nullgroup = null;}//当前线程相关的属性设置nulltarget = null;threadLocals = null;inheritableThreadLocals = null;inheritedAccessControlContext = null;blocker = null;uncaughtExceptionHandler = null;}
【stop】
线程停止方法,@Deprecated,已被弃用
如果线程已经启动,那么将立即终止。 线程停止会解锁所有已经锁定的监视器,这种终止的操作很不安全。
public final void stop() {//安全检查SecurityManager security = System.getSecurityManager();if (security != null) {checkAccess();if (this != Thread.currentThread()) {security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);}}//如果线程状态不是新建,并且线程被挂起,那么将恢复该线程,否则不处理if (threadStatus != 0) {resume();}//停止线程stop0(new ThreadDeath());}
【interrupt】
线程中断,
public void interrupt() {if (this != Thread.currentThread())checkAccess();synchronized (blockerLock) {Interruptible b = blocker;if (b != null) {//设置中断状态interrupt0();//调用阻断程序中的中断方法b.interrupt(this);return;}}interrupt0();}
【interrupted】
【isCCLOverridden】
验证,是否满足安全约束,子类不得覆盖安全性敏感的non-final方法
private static boolean isCCLOverridden(Class<?> cl) {if (cl == Thread.class)return false;//移除子类安全检查结果队列顶部缓存processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);//创建一个弱键WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);缓存中是否有该键对应的对象,如果有,则取出Boolean result = Caches.subclassAudits.get(key);if (result == null) {//安全检查result = Boolean.valueOf(auditSubclass(cl));//检查结果存入缓存Caches.subclassAudits.putIfAbsent(key, result);}return result.booleanValue();}
【processQueue】
如果队列不为空,移除队列头部元素,并将头部元素map中映射也移除
static void processQueue(ReferenceQueue<Class<?>> queue,ConcurrentMap<? extends WeakReference<Class<?>>, ?> map){Reference<? extends Class<?>> ref;while((ref = queue.poll()) != null) {map.remove(ref);}}
【auditSubclass】
子类安全检查方法,通过反射进行检查,线上上下文加载器的方法 getContextClassLoader,setContextClassLoader,确保不被覆盖
private static boolean auditSubclass(final Class<?> subcl) {Boolean result = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {public Boolean run() {//向上查找父类,直到Thread终止for (Class<?> cl = subcl; cl != Thread.class; cl = cl.getSuperclass()) {try {//如果查询到了方法,返回return,未查询到,异常捕获,不做处理cl.getDeclaredMethod("getContextClassLoader", new Class<?>[0]);return Boolean.TRUE;} catch (NoSuchMethodException ex) {}try {Class<?>[] params = {ClassLoader.class};cl.getDeclaredMethod("setContextClassLoader", params);return Boolean.TRUE;} catch (NoSuchMethodException ex) {}}return Boolean.FALSE;}});return result.booleanValue();}
【getContextClassLoader】
获取线程上下文ClassLoader
@CallerSensitivepublic ClassLoader getContextClassLoader() {if (contextClassLoader == null)return null;SecurityManager sm = System.getSecurityManager();if (sm != null) {//如果调用者的类加载器不为空且调用者的类加载器与给定的class参数的祖先不同,那么检查RuntimePermission("getClassLoader")权限ClassLoader.checkClassLoaderPermission(contextClassLoader,Reflection.getCallerClass());}return contextClassLoader;}
【setPriority】
设置优先级,线程组内
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);}}
【destroy】@Deprecated
销毁线程
【suspend】@Deprecated
线程挂起
【resume】@Deprecated
线程恢复被挂起的线程
【activeCount】
当前线程组(包括子组)中活跃的线程数,递归统计
public static int activeCount() {return currentThread().getThreadGroup().activeCount();}
【enumerate】
将当前线程组及其子组的线程复制到指定数组中
public static int enumerate(Thread tarray[]) {return currentThread().getThreadGroup().enumerate(tarray);}
【join】
主线程等待子线程执行,Object.wait(), 必须等待对该对象notify,notifyAll 或者超过了等待时间才会释放
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) {//如果毫秒数等于0,会一直等待,直到线程死亡while (isAlive()) {wait(0);}} else {//如果毫秒数不等于0,超出毫秒数之后会退出等待while (isAlive()) {long delay = millis - now;if (delay <= 0) {break;}wait(delay);now = System.currentTimeMillis() - base;}}}
【dumpStack】
将线程堆栈信息打印,仅用于dubgger
【checkAccess】
安全检查
5.内部类
静态内部类
【Caches】 private static class
缓存子类安全审核结果
private static class Caches {//子类安全结果审核的缓存static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits = new ConcurrentHashMap<>();//已审计子类弱引用队列static final ReferenceQueue<Class<?>> subclassAuditsQueue = new ReferenceQueue<>();}
【WeakClassKey】
类对象的弱键类,继承了弱引用类
题外话:Java 引用类型,强引用,软引用,弱引用,虚引用 ,不了解可以查询一下资料。
static class WeakClassKey extends WeakReference<Class<?>> {private final int hash;//构造方法 父类构造,创建一个弱引用,并且放入给定的队列当中,然后设置一个hash值,indentityHashCode只有当引用对象相同时hashcode相同WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {super(cl, refQueue);hash = System.identityHashCode(cl);}@Overridepublic int hashCode() {return hash;}@Overridepublic boolean equals(Object obj) {if (obj == this)return true;if (obj instanceof WeakClassKey) {Object referent = get();return (referent != null) &&(referent == ((WeakClassKey) obj).get());} else {return false;}}}
枚举类
【State】 线程状态类
public enum State {//新建状态,调用了init方法,未调用runNEW,//运行中,正在虚拟机中执行,如果在等待操作系统分配资源,也是运行中的状态RUNNABLE,//阻塞状态,等待监视器锁定。BLOCKED,//线程等待 Thread.join()/Object.wait() 未指定超时时间,LockSupport.park() 。等待另一个线程 执行 Object.notify/notifyAll ,LockSupprot.unpark。WAITING,//限时等待 Thread.join(timeout) /Object.wait(timeout) Thread.sleep(timeout)指定超时时间,LockSupport.parkNanos()/parkUntil()。 Object.notify/notifyAll 或者超时,状态结束。TIMED_WAITING,//线程终止TERMINATED;}
