Table of Contents
问题:Thread直接调用run()和start()方法的区别?
问题:为什么wait和notify方法不在Thread类里定义?
本篇博客基于jdk1.8
概述
Thread的一个实例,即是一个程序中执行的一个线程,java虚拟机允许一个应用程序同时有多个并发的线程运行。
每一个线程都有一个优先级。优先级高的线程比优先级低的线程优先执行。每一个线程也都可能被标记为一个守护线程。当代码执行到某一个线程去创建另一个线程时,新创建的线程的优先级会初始化成和创建它的线程一样。并且当且仅当创建线程为守护线程时,被创建线程才会被设为守护线程。
当Java虚拟机启动时,通常会有一个单独的非守护进程线程(通常这个非守护线程会去调用一个指定的类的main方法)。Java虚拟机器继续执行线程,直到以下任一一种情况发生:
Runtime类的exit方法被调用并且security manager(安全管理器)允许退出操作操作发生。
所有的非守护线程全部都已经终结,要么通过从调用返回到运行方法或由抛出超出运行的异常方法。
创建一个新的执行线程有两种方法:
声明一个Thread类的子类。这个子类应当去重写Thread类里的run方法。然后子类的实例就可以分配和启动。例如,计算大于指定值的素数的线程可以写成如下:
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
...
}
}
下面的代码就可以创建一个线程并启动它:
PrimeThread p = new PrimeThread(143);
p.start();
创建线程的另一种方法是声明一个类实现Runable接口,这个类需要实现run方法,然后这个类的实例就可以在创建线程时被当做参数传递进去,并且启动,同一个例子的另一种样式如下:
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
...
}
}
然后,下面的代码就可以创建一个线程并启动它:
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
每个线程都有用于标识目的的名称。多个线程可能具有相同的名称。如果创建一个线程时未指定名称,则会为其生成一个新名称。
除非另有说明,否则,向Thread类中的构造函数或方法传递null参数将导致抛出NullPointerException。
另外一点特别有意思的是,Thread类本身就是实现了Runnable接口的一个类。
Thread类中的重要成员变量
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类里一共提供了九个构造方法...其中有一个是非public的方法。
但是这九个构造方法事实上最后都是调用了一个叫做init的方法,该方法定义如下: