线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

继承关系图

线程的创建方式有很多种。常用的有:继承Thread(),重写该类的run()方法;实现Runnable接口,并重写该接口的run()方法。

其实Thread类本身也是实现了Runnable接口,而run()方法最先是在Runnable接口中定义的方法。

主要属性

//  线程的名称
private volatile char name[]; // 线程的优先级
private int priority; // 是否是单步执行
private boolean single_step; // 是否是守护线程
private boolean daemon = false; // JVM虚拟机的状态
private boolean stillborn = false; // 将会被执行的 Runnable
private Runnable target; // 当前线程的组
private ThreadGroup group; // 当前线程的上下文
private ClassLoader contextClassLoader; // 当前线程继承的访问控制权限
private AccessControlContext inheritedAccessControlContext; // 默认线程的自动编号
private static int threadInitNumber;
// 得到下个thread ID
private static synchronized int nextThreadNum() {
return threadInitNumber++;
} // 与当前线程有关的ThreadLocal值
ThreadLocal.ThreadLocalMap threadLocals = null; // 与当前线程相关的InheritableThreadLocal值。
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; // 该线程请求的堆栈大小 默认一般为空 JVM自行分配
private long stackSize; // 当前线程终止后,JVM的私有状态
private long nativeParkEventPointer; // 当前线程的专属ID
private long tid; // 用来生成 thread ID
private static long threadSeqNumber; // 线程状态,0代表线程未启动 Runable
private volatile int threadStatus = 0; // 中断阻塞器:当线程发生IO中断时,需要在线程被设置为中断状态后调用该对象的interrupt方法
volatile Object parkBlocker; // 阻塞器锁,主要用于线程中断
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;

构造方法

我们平时惯用new Thread()方法去创建一个线程,实际上线程初始化的过程中已经完成了很多默认的配置
//  init方法相关参数
// g 线程组
// target 实现 Runnable接口类对象,就是调用 run方法的目标对象
// name 线程名称
// stackSize 栈的大小 该值对JVM而言只是一个建议,JVM会动态选择更合适的值
// 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.toCharArray(); // 设置当前线程为该线程的父线程
Thread parent = currentThread(); // 获取系统的security
SecurityManager security = System.getSecurityManager(); // 没有指定线程组的话,创建的所有线程属于相同的线程组。
if (g == null) {
// 先将secuity的线程组赋给新线程的线程组
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();
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 ThreadID是由JVM分配的,并不是系统的真正线程ID
tid = nextThreadID();
} private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
init(g, target, name, stackSize, null);
} 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);
} public Thread(ThreadGroup group, Runnable target, String name,
long stackSize) {
init(group, target, name, stackSize);
}

native方法

// 获得当前线程
public static native Thread currentThread(); // 使当前线程从 运行状态Running 变为 就绪状态 Runnable
public static native void yield(); // 使当前线程进入休眠状态
public static native void sleep(long millis) throws InterruptedException; // 使线程进入就绪状态 Runnable
private native void start0(); // 判断线程是否为中断状态
private native boolean isInterrupted(boolean ClearInterrupted); // 判断线程是否存活
public final native boolean isAlive(); // 获取所有线程列表
private native static StackTraceElement[][] dumpThreads(Thread[] threads);
private native static Thread[] getThreads(); // 设置线程优先等级
private native void setPriority0(int newPriority); // 停止线程 该方法已被弃用
private native void stop0(Object o); // 线程暂停
private native void suspend0(); // 线程继续执行
private native void resume0(); // 线程中断
private native void interrupt0(); // 设置线程名
private native void setNativeName(String name);

这里不得不说和线程相关的几个Object Native方法。

// 随机唤醒在此对象监视器(锁)上等待的单个线程。
public final native void notify(); // 唤醒所有等待在该对象上的线程。
public final native void notifyAll(); // 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法
public final void wait() throws InterruptedException {
wait(0);
} // 超时等待一段时间,这里的参数是毫秒,也就是等待长达n毫秒,如果没有通知就超时返回。
public final native void wait(long timeout) throws InterruptedException;
我最开始有些疑惑,为什么wait(),notify(),notifyAll()用来操作线程会定义在Object类中?
不妨我们先做一个假设:将wait、notify和线程队列都放到Thread中,那么在wait、notify的调度过程中必然要求某个Thread知道其他所有Thread的信息,显然是不合理的。
而放到对象中,让对象维护所有竞争锁线程的队列,各个线程无必然联系。
 

关键方法

start() 启动线程

public synchronized void start() {
// 判断线程状态是否启动,不允许同一线程启动2次!
if (threadStatus != 0)
throw new IllegalThreadStateException(); // 向线程组中添加当前线程
group.add(this); // 使线程进入就绪状态 Runnable
boolean started = false;
try {
start0();
started = true;
} finally {
try {
// 若线程启动失败,则通知该线程组,回滚线程组状态
// 该线程被视为线程组的未启动成员,并允许后续尝试启动该线程。
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}

checkAccess() 检查当前线程是否有修改权限,该方法在线程状态变更前多次被调用

public final void checkAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
// 通过Java安全管理器检查当前线程是否有修改权限
security.checkAccess(this);
}
}

run()  使线程从就绪状态 Runnable转化为运行状态 Running   -todo线程启动过程中由start到run的过程非常复杂。

public void run() {
// 调用 run方法的目标对象
if (target != null) {
target.run();
}
}

exit()  该方法 run方法执行完成后调用,在线程结束退出之前进行清理工作。

private void exit() {
// 释放资源
if (group != null) {
group.threadTerminated(this);
group = null;
} target = null; threadLocals = null;
inheritableThreadLocals = null;
inheritedAccessControlContext = null;
blocker = null;
uncaughtExceptionHandler = null;
}
stop() stop方法是不安全的,它会立即停止线程执行,线程的后续执行不连贯。可能会导致一些清理性的工作的得不到完成,如文件,数据库等的关闭。故被标记为@Deprecated

@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(); // Wake up thread if it was suspended; no-op otherwise
} stop0(new ThreadDeath());
}

interrupt()  中断线程

public void interrupt() {
if (this != Thread.currentThread())
checkAccess(); synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // Just to set the interrupt flag
b.interrupt(this);
return;
}
}
interrupt0();
}
setPriority()、getPriority()  设置、获取线程优先级
public final void setPriority(int newPriority) {
ThreadGroup g;
checkAccess();
// 线程优先级范围仅分 1~10 级
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
throw new IllegalArgumentException();
}
if((g = getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
setPriority0(priority = newPriority);
}
} public final int getPriority() {
return priority;
}
 
join()  在当前线程中调用另一个线程的join()方法,使当前线程转入阻塞状态,直到另一个进程运行结束,当前线程再由阻塞转为就绪状态。
public final void join() throws InterruptedException {
join(0);
} 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;
}
}
}

setDaemon() 将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。

public final void setDaemon(boolean on) {
checkAccess();
// 该方法必须在启动线程前调用
if (isAlive()) {
throw new IllegalThreadStateException();
}
daemon = on;
}

盘一盘 Thread源码的更多相关文章

  1. 从Thread.start()方法看Thread源码,多次start一个线程会怎么样

    这篇文章作为Thread类源码剖析的补充,从一个侧面来看Thread源码.也解答了面试高频问题:"多次start一个线程会怎么样?" 答案是:java.lang.IllegalTh ...

  2. java 并发编程——Thread 源码重新学习

    Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...

  3. Handler、Looper、MessageQueue、Thread源码分析

    关于这几个之间的关系以及源码分析的文章应该挺多的了,不过既然学习了,还是觉得整理下,印象更深刻点,嗯,如果有错误的地方欢迎反馈. 转载请注明出处:http://www.cnblogs.com/John ...

  4. Thread源码分析

    本文为转载,请珍惜别人的劳动成果,注明转载地址:http://www.cnblogs.com/gw811/archive/2012/10/15/2724602.html 1.Runnable接口源码: ...

  5. Thread源码剖析

    前言 昨天已经写了: 多线程三分钟就可以入个门了! 如果没看的同学建议先去阅读一遍哦~ 在写文章之前通读了一遍<Java 核心技术 卷一>的并发章节和<Java并发编程实战>前 ...

  6. Thread源码分析-java8

    1.Thread特性分析 守护线程Daemon 定性:支持性线程,主要用于程序中后台调度以及支持性工作. 当JVM中不存在Daemon线程时,JVM将会退出. 将一个线程设定为Daemon的方法: 调 ...

  7. Java中Thread源码剖析

    本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 关于线程,用很长时间了,主线程下的子线程去做一些事情,就是一个代理模式,主线程分代理权给子线程,子线 ...

  8. 并发编程学习笔记(七、Thread源码分析)

    目录: 常见属性 构造函数 start() run() 常见属性: /** * 线程名称 */ private volatile String name; /** * 线程优先级 */ private ...

  9. java Thread源码分析(二)

    一.sleep的使用 public class ThreadTest { public static void main(String[] args) throws InterruptedExcept ...

随机推荐

  1. docker search

    命令:docker search [root@iZ943kh74qgZ ~]# docker search --help Usage: docker search [OPTIONS] TERM Sea ...

  2. OpenJudge_1936:All in All

    描述 You have devised a new encryption technique which encodes a message by inserting between its char ...

  3. 16.libgdx根据配置文件生成布局(未完)

    思路: screen分为普通和复杂两种,普通的功能大部分是页面跳转以及简单的crud数据,复杂的单独弄出来 跳转普通的screen,直接根据配置文件调整设置 <layouts> <l ...

  4. 字符缓冲流 Day20

    package com.sxt.prac; /* * 缓冲流之字符缓冲流 defaultCharBufferSize = 8192; * 1.读入到程序 * 2.程序写到文件 * 3.采用循环边读边写 ...

  5. Redis源码解析:07压缩列表

    压缩列表(ziplist)是列表键和哈希键的底层实现之一.当列表键只包含少量列表项,并且每个列表项要么是小整数值,要么是长度较短的字符串时:或者当哈希键只包含少量键值对,并且每个键值对的键和值要么是小 ...

  6. install tushare in python 3.6

    install tushare (D:\Anaconda3) C:\Users\Administrator>pip install tushare Collecting tushare Down ...

  7. 从零学React Native之01创建第一个程序

    本篇首发于简书 欢迎关注 上一篇文章是时候了解React Native了介绍了React Native.大家应该对React Native有个初步的认识. 接下来我们就可以初始化一个React Nat ...

  8. ansible api 通过python 方式调用

    pip3 install ansible Linux下面安装 Windows 安装没成功 from ansible.parsing.dataloader import DataLoader #读取ya ...

  9. Open Source Software List: The Ultimate List

    http://www.datamation.com/open-source/ Accessibility 1. The Accessibility Project The Business Value ...

  10. AtCoder Beginner Contest 075 C Bridge(割边)

    求割边个数.Tarjan的板子.. #include <bits/stdc++.h> using namespace std; const int MAXN = 55; const int ...