目录
1、Thread.State线程状态(NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、ERMINATED)
2、Thread.UncaughtExceptionHandler
Class Thread
继承了 java.lang.Object
实现了 Runnable接口
继承Thread的类:ForkJoinWorkerThread
一、线程介绍
thread是程序中的执行线程。Java虚拟机允许应用程序同时运行多个执行线程。
每个线程都有优先级。高优先级线程优先于低优先级线程执行。每个线程可以也可以不被标记为守护进程。当运行在某个线程中的代码创建一个新的Thread对象时,新线程的优先级最初被设置为与创建线程的优先级相等,当且仅当创建线程是一个守护线程时,新线程就是一个守护线程。
当Java Virtual Machine启动时,通常有一个非守护处理线程(它通常调用某个指定类的main方法)。Java虚拟机继续执行线程,直到出现以下情况:
- Runtime类的exit方法被调用,并且安全管理器已经允许exit操作。
- 所有非守护线程的线程都已经死亡,原因要么是从对run方法的调用返回,要么抛出一个传播到run方法之外的异常。
二、创建线程的两种方法
1、声明一个类是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();
2、声明一个实现Runnable接口的类
这个类然后实现run方法。然后可以分配类的实例,在创建Thread时作为参数传递,并启动。
另一种风格的相同示例如下:
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();
每个线程都有一个用于标识的名称。
多个线程可以有相同的名称。
如果在创建线程时没有指定名称,则会为其生成一个新名称。
除非另有说明,否则将null参数传递给该类中的构造函数或方法将导致抛出NullPointerException。
查看其他相关部分:
三、Thread内部类
1、Thread.State线程状态(NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、ERMINATED)
/**
* 一个线程的状态。线程可以处于下列状态之一:
* NEW: 尚未启动的线程处于这种状态。
* RUNNABLE: 在Java虚拟机中执行的线程就是这种状态。
* BLOCKED: 等待监视器锁而被阻塞的线程就处于这种状态。
* WAITING: 无限等待另一个线程执行特定操作的线程就处于这种状态。
* TIMED_WAITING: 在指定的等待时间内等待另一个线程执行操作的线程就是这种状态。
* ERMINATED: 已退出的线程处于这种状态。
* 线程在给定的时间点只能处于一种状态。
* 这些状态是不反映任何操作系统线程状态的虚拟机状态。
*
* @since 1.5
* @see #getState
*/
public enum State {
/**
* 尚未启动的线程的线程状态。
*/
NEW,
/**
* 可运行线程的线程状态。
* 处于可运行状态的线程正在Java虚拟机中执行,但它可能正在等待来自操作系统(如处理器)的其他资源。
*/
RUNNABLE,
/**
* 等待监视器锁的线程阻塞的线程状态。
* 处于阻塞状态的线程正在等待监视器锁进入同步块/方法或在调用后重新进入同步块/方法
* {@link Object#wait() Object.wait}.
*/
BLOCKED,
/**
* 等待线程的线程状态。
* 由于调用以下方法之一,线程处于等待状态:
* 没有超时的Object.wait()
* 没有超时的Thread.join
* LockSupport.park()
*
* 处于等待状态的线程正在等待另一个线程执行特定的操作。
* 例如,在一个对象上调用了Object.wait()的线程正在等待另一个线程在该对象上调用Object.notify()或Object.notifyAll()。
* 调用Thread.join()的线程正在等待指定的线程终止。
*/
WAITING,
/**
* 具有指定等待时间的等待线程的线程状态。
* 线程处于定时等待状态,因为调用了下列方法之一,并指定等待时间:
* Thread.sleep()
* Object.wait(long) 与超时
* Thread.join(long) 与超时
* LockSupport.parkNanos
* LockSupport.parkUntil
*/
TIMED_WAITING,
/**
* 终止线程的线程状态。
* 线程已完成执行。
*/
TERMINATED;
}
2、Thread.UncaughtExceptionHandler
/**
* 接口,用于在线程因未捕获异常而突然终止时调用的处理程序。
* 当一个线程由于未捕获的异常而即将终止时,Java虚拟机将使用getUncaughtExceptionHandler查询该线程的UncaughtExceptionHandler,
* 并将调用该处理程序的uncaughtException方法,将线程和异常作为参数传递。
* 如果一个线程没有显式地设置它的UncaughtExceptionHandler,那么它的ThreadGroup对象就会充当它的UncaughtExceptionHandler。
* 如果ThreadGroup对象对处理异常没有特殊要求,它可以将调用转发给getDefaultUncaughtExceptionHandler默认未捕获异常处理程序}。
*
* @see #setDefaultUncaughtExceptionHandler
* @see #setUncaughtExceptionHandler
* @see ThreadGroup#uncaughtException
* @since 1.5
*/
@FunctionalInterface
public interface UncaughtExceptionHandler {
/**
* 方法在给定线程由于给定的未捕获异常而终止时调用。
* 此方法抛出的任何异常都会被Java虚拟机忽略。
* @param t the thread
* @param e the exception
*/
void uncaughtException(Thread t, Throwable e);
}
四、Thread类常量字段
/**
* 线程可以拥有的最低优先级。
*/
public final static int MIN_PRIORITY = 1;
/**
* 分配给线程的默认优先级。
*/
public final static int NORM_PRIORITY = 5;
/**
* 线程可以拥有的最大优先级。
*/
public final static int MAX_PRIORITY = 10;
五、Thread类构造方法
/**
* 分配一个新的 Thread 对象.
* 这个构造函数与Thread(ThreadGroup, Runnable, String), 参数分别传入(null, null, gname)的效果相同,其中gname是一个新生成的名称。
* 自动生成的名称的形式是“Thread-”+n,其中n是一个整数。
*/
public Thread(){
init(null,null,"Thread-"+nextThreadNum(),0);
}
/**
* 分配一个新的 Thread 对象.
* 这个构造函数与Thread(ThreadGroup, Runnable, String), 参数分别传入(null, target, gname)的效果相同,其中gname是一个新生成的名称。
* 自动生成的名称的形式是“Thread-”+n,其中n是一个整数。
*
* @param target 在此线程启动时调用其run方法的对象。如果为空,这个类的run方法什么都不做。
*/
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
/**
* 分配一个新的 Thread 对象.
* 这个构造函数与Thread(ThreadGroup, Runnable, String), 参数分别传入(null, target, name)的效果相同。
*
* @param target 在此线程启动时调用其run方法的对象。如果为null,则调用该线程的run方法。
* @param name 新线程的名称
*/
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
/**
* 分配一个新的 Thread 对象.
* 这个构造函数与Thread(ThreadGroup, Runnable, String), 参数分别传入(null, null, name)的效果相同。
*
* @param name 新线程的名称
*/
public Thread(String name) {
init(null, null, name, 0);
}
/**
* 分配一个新的 Thread 对象.
* 这个构造函数与Thread(ThreadGroup, Runnable, String), 参数分别传入(group, null, name)的效果相同。
*
* @param group
* 线程组。如果null且存在安全管理器,则组由SecurityManager#getThreadGroup SecurityManager.getThreadGroup()确定。
* 如果没有安全管理器或者SecurityManager.getThreadGroup()返回null,则组被设置为当前线程的线程组。
*
* @param name
* 新线程的名字
*
* @throws SecurityException
* 如果当前线程不能在指定的线程组中创建线程,抛出这个异常
*/
public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);
}
/**
* 分配一个新的 Thread 对象.
* 这个构造函数与Thread(ThreadGroup, Runnable, String), 参数分别传入(group, target, gname)的效果相同,其中gname是一个新生成的名称。
* 自动生成的名称的形式是“Thread-”+n,其中n是一个整数。
*
* @param group
* 线程组,如果为null且存在安全管理器,则group由SecurityManager.getThreadGroup()确定。
* 如果没有安全管理器或者SecurityManager.getThreadGroup()返回null,则组被设置为当前线程的线程组。
*
* @param target
* 在此线程启动时调用其run方法的对象。
* 如果为空,则调用此线程的run方法。
*
* @throws SecurityException
* 如果当前线程不能在指定的线程组中创建线程,抛出这个异常
*/
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
/**
* 分配一个新的Thread对象,使其以target作为其运行对象,以指定的名称作为其名称,并属于group引用的线程组。
* 如果存在安全管理器,它的SecurityManager.checkAccess(ThreadGroup)方法将以ThreadGroup作为参数调用。
* 另外,它的checkPermission方法被RuntimePermission("enableContextClassLoaderOverride")权限调用时,直接或间接地被覆盖getContextClassLoader或setContextClassLoader方法的子类的构造函数调用。
* 新创建的线程的优先级设置为与创建它的线程(即当前运行的线程)的优先级相等。
* 方法setPriority(int newPriority)可以用来将优先级更改为一个新值。
*
* 当且仅当创建线程的线程当前被标记为守护线程时,新创建的线程最初被标记为守护线程。
* 方法setDaemon(boolean on)可以用来改变线程是否为守护进程。true,守护线程。false,非守护线程。
*
* @param group
* 线程组。如果为空且存在安全管理器,则组由SecurityManager.getThreadGroup()确定。
* 如果没有安全管理器或者SecurityManager.getThreadGroup()返回null,则组被设置为当前线程的线程组。
*
* @param target
* 在此线程启动时调用其run方法的对象。
* 如果为空,则调用此线程的run方法。
*
* @param name
* 新线程的名字。
*
* @throws SecurityException
* 如果当前线程不能在指定的线程组中创建线程或不能重写上下文类装入器方法,抛出此异常。
*/
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
}
/**
* 分配一个新的Thread对象,使其以target作为其运行对象,以指定的名称作为其名称,并属于由组引用的线程组,并具有指定的堆栈大小。
*
* 这个构造函数和Thread(ThreadGroup,Runnable,String)是一样的,只是它允许指定线程堆栈的大小。
* 堆栈大小是虚拟机为这个线程的堆栈分配的地址空间的大约字节数。
* stackSize参数的影响(如果有的话)是高度依赖于平台的。
*
* 在某些平台上,为stackSize参数指定更高的值可能允许线程在抛出StackOverflowError之前实现更大的递归深度。
* 类似地,指定较低的值可以允许并发存在更多的线程,而不会抛出OutOfMemoryError(或其他内部错误)。
* stackSize参数的值与最大递归深度和并发级别之间关系的细节取决于平台。
* 在某些平台上,stackSize参数的值可能没有任何影响。
*
* 虚拟机可以自由地将stackSize参数作为一个建议。
* 如果指定的值对于平台来说是不合理的低,虚拟机可能会使用一些特定于平台的最小值;
* 如果指定的值过高,虚拟机可能会使用特定于平台的最大值。
* 同样,虚拟机可以根据自己的需要随意上下舍入指定的值(或者完全忽略它)。
*
* 将stackSize参数的值设为零将导致该构造函数的行为与Thread(ThreadGroup, Runnable, String)构造函数完全相同。
*
* 由于这个构造函数的行为依赖于平台,因此在使用它时应该格外小心。
* 执行给定计算所需的线程堆栈大小可能因JRE实现的不同而不同。
* 根据这种变化,可能需要仔细地调优堆栈大小参数,并且可能需要对要在其上运行应用程序的每个JRE实现重复调优。
*
* 实现注意:鼓励Java平台实现者记录与stackSize参数相关的实现行为。
*
* @param group
* 线程组。如果null且存在安全管理器,则组由SecurityManager#getThreadGroup SecurityManager.getThreadGroup()确定。
* 如果没有安全管理器或者SecurityManager.getThreadGroup()返回null,则组被设置为当前线程的线程组。
*
* @param target
* 在此线程启动时调用其run方法的对象。
* 如果为空,则调用此线程的run方法。
*
* @param name
* 新线程的名字。
*
* @param stackSize
* 新线程所需的堆栈大小,或表示忽略此参数的0。
*
* @throws SecurityException
* 如果当前线程不能在指定的线程组中创建线程,抛出此异常。
*
* @since 1.4
*/
public Thread(ThreadGroup group, Runnable target, String name, long stackSize) {
init(group, target, name, stackSize);
}
/**
* javase8中没有这个构造方法。javase 9之后包含此构造方法。
* 分配一个新的Thread对象,以便它以target作为其运行对象,以指定的名称作为其名称,属于组引用的线程组,具有指定的stackSize,并在inheritThreadLocals为真时继承可继承线程局部变量的初始值。
* 这个构造函数与Thread(ThreadGroup,Runnable,String,long)是相同的,只是增加了从构造线程继承可继承的线程局部变量的初始值,或者不继承。这允许对可继承的线程局部变量进行更细粒度的控制。在为inheritThreadLocals传递false值时必须小心,因为如果新线程执行需要继承特定线程本地值的代码,那么它可能会导致意外行为。
* 为inheritThreadLocals参数指定true值将使该构造函数的行为与Thread(ThreadGroup, Runnable, String, long)构造函数完全相同。
*
* @param group - 线程组。如果为空且存在安全管理器,则组由SecurityManager.getThreadGroup()确定。如果没有安全管理器或者SecurityManager.getThreadGroup()返回null,则组被设置为当前线程的线程组。
* @param target - 在此线程启动时调用其run方法的对象。如果为空,则调用此线程的run方法。
* @param name - 新线程的名字
* @param stackSize - 新线程所需的堆栈大小,或表示忽略此参数的0。
* @param inheritThreadLocals - 如果为true,则从构造线程继承可继承线程局部变量的初始值,否则不继承初始值。
*
* @throws
* SecurityException - 如果当前线程不能在指定的线程组中创建线程,抛出此异常。
*/
public Thread(ThreadGroup group, Runnable target, String name, long stackSize, boolean inheritThreadLocals){}
六、Thread方法
修饰符和类型 | 方法名 | 描述 |
static int | activeCount() | 返回当前线程的线程组及其子组中活动线程的估计数量。 |
final void | checkAccess() | 已弃用,供删除:该API元素可能会在未来的版本中被删除。 此方法仅在与Security Manager结合使用时有用,Security Manager已被弃用,并可能在未来的版本中被删除。 |
protected Object | clone() | 作为线程抛出CloneNotSupportedException不能被有意义地克隆。 |
int | countStackFrames() | 已弃用,供删除:该API元素可能会在未来的版本中被删除。 这种方法最初设计用于计算堆栈帧的数量,但结果从来没有定义良好,而且它依赖于线程挂起。 |
static Thread | currentThread() | 返回对当前执行的线程对象的引用。 |
static void | dumpStack() | 将当前线程的堆栈跟踪打印到标准错误流。 |
static int | enumerate(Thread[] tarray) | 将当前线程的线程组及其子组中的每个活动线程复制到指定的数组中。 |
static Map<Thread,StackTraceElement[]> | getAllStackTraces() | 返回所有活动线程的堆栈跟踪映射。 |
ClassLoader | getContextClassLoader() | 返回此线程的上下文ClassLoader。 |
static Thread.UncaughtExceptionHandler | getDefaultUncaughtExceptionHandler() | 返回当线程因未捕获异常而突然终止时调用的默认处理程序。 |
long | getId() | 返回此线程的标识符。 |
final String | getName() | 返回线程的名称。 |
StackTraceElement[] | getPriority() | 返回线程的优先级。 |
Thread.State | getStackTrace() | 返回表示此线程的堆栈转储的堆栈跟踪元素数组 |
final ThreadGroup | getThreadGroup() | 返回此线程所属的线程组。 |
Thread.UncaughtExceptionHandler | getUncaughtExceptionHandler() | 返回当此线程因未捕获的异常而突然终止时调用的处理程序。 |
static boolean | holdsLock(Object obj) | 当且仅当当前线程持有指定对象上的监视器锁时,返回true。 |
void | interrupt() | 中断线程。 |
static boolean | interrupted() | 测试当前线程是否已中断。 |
final boolean | isAlive() | 测试此线程是否活动。 |
final boolean | isDaemon() | 测试此线程是否为守护线程。 |
boolean | isInterrupted() | 测试此线程是否已被中断。 |
final void | join() | 等待线程死亡。 |
final void | join(long millis) | 等待线程死亡的时间最多为millis毫秒。 |
final void | join(long millis, int nanos) | 等待线程死亡的时间最多为millis毫秒加nanos纳秒。 |
final void | onSpinWait() | 指示调用者暂时无法进行,直到其他活动的一部分发生一个或多个操作。 |
static void | resume() | 已弃用: 该API元素可能会在未来的版本中被删除。 此方法仅用于suspend(),该方法已被弃用,因为它容易出现死锁。 |
void | run() | 如果这个线程是使用一个单独的Runnable运行对象构造的,那么该Runnable对象的run方法被调用;否则,此方法不执行任何操作并返回。 |
void | setContextClassLoader(ClassLoader cl) | 为这个线程设置上下文类加载器。 |
final void | setDaemon(boolean on) | 将此线程标记为守护线程或用户线程。 |
static void | setDefaultUncaughtExceptionHandler (Thread.UncaughtExceptionHandler eh) | 设置当线程因未捕获的异常而突然终止且未为该线程定义其他处理程序时调用的默认处理程序。 |
final void | setName(String name) | 将此线程的名称更改为与参数名称相等。 |
final void | setPriority(int newPriority) | 更改此线程的优先级。 |
void | setUncaughtExceptionHandler (Thread.UncaughtExceptionHandler eh) | 设置当此线程因未捕获的异常而突然终止时调用的处理程序。 |
static void | sleep(long millis) | 使当前正在执行的线程休眠(暂时停止执行)指定的毫秒数,取决于系统计时器和调度器的精度和准确性。 |
static void | sleep(long millis, int nanos) | 使当前正在执行的线程休眠(暂时停止执行),休眠时间为指定的毫秒数加上指定的纳秒数,具体时间取决于系统计时器和调度器的精度。 |
void | start() | 使线程开始执行;Java虚拟机调用这个线程的run方法。 |
void | stop() | 已弃用:该API元素可能会在未来的版本中被删除。 这种方法本身就不安全。 |
final void | suspend() | 已弃用:该API元素可能会在未来的版本中被删除。 这个方法已经被弃用,因为它本身就容易死锁。 |
String | toString() | 返回此线程的字符串表示形式,包括线程的名称、优先级和线程组。 |
static void | yield() | 提示调度器当前线程愿意放弃其当前对处理器的使用。 |