线程属性
1. 线程名
没必要再说了吧......
2. 未捕获异常的处理器
线程的 run
方法不能抛出任何检查型异常,但是,非检查型异常可能会导致线程终止,在这种情况下线程会死亡。
实际上,在线程死亡之前,异常会传递到一个用于处理未捕获异常的处理器。这个处理器必须属于一个实现了 Thread.UncaughtExceptionHandler
接口的类。
Thread
类的相关方法:
static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh)
static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler()
void setUncaughtExceptionHandler(UncaughtExceptionHandler eh)
UncaughtExceptionHandler getUncaughtExceptionHandler()
3. 线程优先级
每个线程执行时都具有一定的优先级,优先级高的线程获得较多的执行机会。默认情况下,一个线程会继承构造它的那个线程的优先级。
Thread
类提供了 setPriority(int newPriority), getPriority()
方法来设置和返回指定线程的优先级,其中 setPriority
方法的参数可以是一个整数,范围是 1~10 之间,也可以使用 Thread
类的如下三个静态常量:
静态常量 | 说明 |
---|---|
MAX_PRIORITY | 其值为 10 |
MIN_PRIORITY | 其值为 1 |
NORM_PRIORITY | 其值为 5 |
虽然 Java 提供了 10 个优先级级别,但这些优先级级别需要操作系统的支持,遗憾的是,不同操作系统上的优先级并不相同,而且也不能很好地和 Java 的 10 个优先级对应,如 Windows 2000 仅提供了 7 个优先级。
因此应该尽量避免直接为线程指定优先级,应该使用
MAX_PRIORITY, MIN_PRIORITY, NORM_PRIORITY
三个静态常量来设置优先级,这样才可以保证程序具有最好的可移值性。
在默认情况下,main
线程具有普通优先级。
示例代码:
class PriorityTest extends Thread {
public PriorityTest(String name) {
super(name);
}
public void run() {
for (int i = 0; i < 50; ++i) {
System.out.println(getName() + ",其优先级是:" + getPriority() + i);
}
}
public static void main(String[] args) {
// 改变主线程的优先级
Thread.currentThread().setPriority(6);
for (int i = 0; i < 30; ++i) {
if (i == 10) {
PriorityTest low = new PriorityTest("低级线程");
low.start();
System.out.println("创建之初的优先级:" + low.getPriority());
// 设置该线程为最低优先级
low.setPriority(Thread.MIN_PRIORITY);
}
if (i == 20) {
PriorityTest high = new PriorityTest("高级线程");
high.start();
System.out.println("创建之初的优先级:" + high.getPriority());
// 设置该线程为最高优先级
high.setPriority(Thread.MAX_PRIORITY);
}
}
}
}
4. 守护线程
有一种线程,它是在后台运行的,其任务是为其他的线程提供服务,这种线程被称为后台线程,又称为守护线程。JVM 的垃圾回收线程就是典型的守护线程。
守护线程的特点是:如果所有的前台线程都死亡,守护线程会自动死亡。前台线程死亡后,JVM 会通知守护线程死亡,但从它接收指令到做出响应,需要一定时间。
调用 Thread
对象的 setDaemon(true)
方法可将指定线程设置成守护线程。且若要将某个线程设置为守护线程,必须在该线程启动之前设置,即 setDaemon(true)
必须在 start()
方法之前调用,否则会引发 IllegalThreadStateException
异常。
并不是所有的线程默认都是前台线程,有些线程默认就是守护线程:前台线程创建的子线程默认是前台线程,后台线程创建的子线程默认是守护线程。
守护线程示例:
class DaemonThread extends Thread {
public void run() {
for (int i = 0; i < 1000; ++i) {
System.out.println(getName() + " " + i);
}
}
public static void main(String[] args) {
DaemonThread t = new DaemonThread();
// 将此线程设置为后台线程
t.setDaemon(true);
t.start();
for (int i = 0; i < 10; ++i) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
// -----程序执行到此处,前台线程(main线程)结束
// 后台线程也应该随之结束
}
}
Thread
类的相关方法:
void setDaemon(boolean isDaemon)
:标识该线程为守护线程或用户线程,这一方法必须在线程启动之前调用。boolean isDaemon()
:判断指定线程是否为守护线程