一、定义
public
class Thread implements Runnable {}
可以看到Thread类本身也继承了Runnable接口
二、主要属性
private volatile String name; //线程的名字
private int priority; //线程优先级
/* Whether or not to single_step this thread. */
private boolean single_step;
/* Whether or not the thread is a daemon thread. */
private boolean daemon = false; //是否是守护线程
/* What will be run. */
private Runnable target; //将会被执行的Runnable.
/* The group of this thread */
private ThreadGroup group; //这个线程的组
/* The context ClassLoader for this thread */
private ClassLoader contextClassLoader; //这个线程的上下文
/* The inherited AccessControlContext of this thread */
private AccessControlContext inheritedAccessControlContext; //继承的请求控制
/* For autonumbering anonymous threads. */
private static int threadInitNumber; //默认线程的自动编号
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null; //当前线程附属的ThreadLocal,而ThreadLocalMap会被ThreadLocal维护)
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
// 主要作用:为子线程提供从父线程那里继承的值
//在创建子线程时,子线程会接收所有可继承的线程局部变量的初始值,以获得父线程所具有的值
// 创建一个线程时如果保存了所有 InheritableThreadLocal 对象的值,那么这些值也将自动传递给子线程
//如果一个子线程调用 InheritableThreadLocal 的 get() ,那么它将与它的父线程看到同一个对象
/*
* The requested stack size for this thread, or 0 if the creator did
* not specify a stack size. It is up to the VM to do whatever it
* likes with this number; some VMs will ignore it.
*/
private long stackSize; //该线程请求的堆栈大小 默认一般都是忽略
/*
* Thread ID
*/
private long tid; // 每个线程都有专属ID,但名字可能重复
/* For generating thread ID */
private static long threadSeqNumber; //用来生成thread ID
/* Java thread status for tools,
* initialized to indicate thread 'not yet started'
*/
private volatile int threadStatus = 0; //标识线程状态,默认是线程未启动
/* The object in which this thread is blocked in an interruptible I/O
* operation, if any. The blocker's interrupt method should be invoked
* after setting this thread's interrupt status.
*/
private volatile Interruptible blocker; //阻塞器锁,主要用于处理阻塞情况
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;//线程的优先级中最小的
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5; //线程的优先级中第二的同时也是默认的优先级
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10; //最高的优先级
三、构造方法
Thread()
Thread(Runnable target)
Thread(Runnable target, String name)
Thread(String name)
Thread(ThreadGroup group, Runnable target)
Thread(ThreadGroup group, Runnable target, String name)
Thread(ThreadGroup group, Runnable target, String name, long stackSize)
Thread(ThreadGroup group, String name)
这几个构造方法事实上最后都是调用了一个叫做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();
if (g == null) {
/* Determine if it's an applet or not */
/* If there is a security manager, ask the security manager
what to do. */
if (security != null) {
g = security.getThreadGroup();
}
/* If the security doesn't have a strong opinion of the matter
use the parent thread group. */
if (g == null) {
g = parent.getThreadGroup();
}
}
/* checkAccess regardless of whether or not threadgroup is
explicitly passed in. */
g.checkAccess();
/*
* Do we have the required permissions?
*/
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 (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
/* Set thread ID */
tid = nextThreadID();
}
该方法一共六个参数:
1.ThreadGroup 线程组,默认将父线程的ThreadGroup作为子线程的ThreadGroup
2.Runnable target 一个Runnable对象,即调用run方法的对象
3.String name 新线程的名字
4.long stackSize 新线程分配所需堆栈的大小
5.AccessControlContext acc 权限控制
6.boolean inheritThreadLocals 是否继承ThreadLocals, 这个参数总是true。
四、主要方法
1.start()方法
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
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 */
}
}
}
启动一个线程两次会抛出IllegalThreadStateException
start()方法核心实现代码为方法start0(),是一个本地方法,在这个本地方法的实现当中,虚拟机会去调用该线程的run方法。
2.run()方法
@Override
public void run() {
if (target != null) {
target.run();
}
}
target定义如下:
private Runnable target;
target就是线程传入的Runnable实例。
注:直接调用run()方法相当于在当前线程执行一个普通方法,只有调用start()方法才会启动新的线程。
之所以采用start()调用run()方法是将线程本身和要执行的任务解耦。
3.interrupt()方法
调用interrupt()方法仅仅是将该线程的中断状态设置为true,它并不会真正中断一个正在运行的线程,只是发出中断请求而已。
阻塞库方法如wait(),sleep(),join()在阻塞时一直检查中断状态,若检测到标志位置为true,则抛出InterruptedException,并清除中断状态。
isInterrupted()方法返回线程中断状态
静态的interrupted()方法返回线程中断状态,并清除标志位。
优雅停止线程的方式:
(1)使用volatile变量
public class ThreadCloseGraceful { private static class Worker extends Thread { private volatile boolean start = true; @Override public void run() { while (start) { //doSometing() } } public void shutdown() { this.start = false; } } }
(2)中断
public class ThreadCloseGraceful2 { private static class Worker extends Thread { @Override public void run() { while (true) { if (Thread.interrupted()) break; //doSometing() } } } }
4.join()方法
调用join方法的线程对象执行完run方法中的任务且销毁之后才继续执行后面的代码。
5.sleep()方法(静态)
sleep()方法和wait()方法的区别?
(1)sleep()方法属于Thread类的静态方法,而wait()是Object的成员方法。
(2)sleep()方法没有释放锁,而wait()方法释放了锁
(3)sleep必须捕获异常
(4)wait需要依赖对象,需要notify()或者notifyall()唤醒。
6.yield()方法(静态)
让出当前线程执行权,使当前线程从执行状态(运行状态)变为可执行态(就绪状态)。
7.其他常用方法
static Thread currentThread()返回当前线程
setContextClassLoader(ClassLoader cl)设置线程上下文类加载器
getContextClassLoader()获取线程上下文类加载器
getState()获取线程状态
setPriority(int newPriority)设置线程优先级
getPriority()获取线程优先级
setName(String name)设置线程名字
getName()获取线程名字
setDaemon(boolean on) 设置是否为守护线程,默认继承父线程的属性
isDaemon()判断是否为守护线程