本文主要讨论线程的各种属性,包括:主线程、线程优先级、守护线程、线程组、处理未捕获异常的处理器。
  主线程     任何一个Java程序启动时,至少会启动一个线程执行main方法,这个线程就被称为主线程(main
thread)。它是产生其它线程的线程,即:其它所有线程的主线程的子孙线程。通常,主线程都是最后结束的,因为它要执行其它子线程的关闭工作。   线程优先级  
  计算机只有一个CPU,各个线程轮流获取CPU的使用权,才能执行任务。为了判断优先执行哪个线程,给每一个线程设置了一个优先级,优先级高的线程将会被优先执行。默认情况下,每个线程的优先级继承它的父线程(创建该线程的线程)的优先级。优先级是1-10之间的整数,一般情况下,线程默认的优先级是5。常用的优先级有三个(1
: MIN_PRIORITY、 5 : NORM_PRIORITY、 10 : MAX_PRIORITY)。 public class Priority {
@Testpublic void defaultPriority(){ int mainThreadPriority =
Thread.currentThread().getPriority(); System.out.println("default priority is
"+mainThreadPriority);//5 } @Test public void extendFather(){ Thread mainThread
= Thread.currentThread(); mainThread.setPriority(4); int mainThreadPriority =
mainThread.getPriority(); System.out.println("main thread's priority is
"+mainThreadPriority);//4 Thread t1 = new Thread(() ->
System.out.println(Thread.currentThread().getName()),"t1"); System.out.println(
"t1 thread's priority is "+t1.getPriority());//4 } }
相关API:
void setPriority(int priority) 设置线程优先级 int getPriority()       获取线程优先级
 

守护线程
   
守护线程的唯一作用就是为其它线程提供服务,永远不要在守护线程中访问固有资源,比如文件、数据库等。当所有的用户线程都结束后,守护线程才会结束。且当只剩下守护线程,虚拟机就会退出。
      默认情况下,由用户线程创建的线程仍是用户线程,由守护线程创建的线程仍是守护线程。       Java虚拟机的垃圾回收线程就是典型的守护线程。  
    相关API: void setDaemon(boolean isdaemon) 设置线程为守护线程或者用户线程。该方法必须在线程启动之前调用。
boolean isDaemon()          判断该线程是否为后台线程
 

线程组
   
线程组是一个可以统一管理的线程集合,线程组也可以包含其它线程组。默认情况下,所有的线程属于同一个线程组。线程只能访问自己所在线程组的信息,不能访问其它线程组的信息,包括该线程组的父线程组。
      建议不要使用线程组(已经有更好的特性用于线程集合的操作) public class ThreadGroupDemo { public static
void print(){ Thread thread = Thread.currentThread();
System.out.println(thread.getThreadGroup().getName()+"-"+thread.getName()); }
public static void main(String[] args) { ThreadGroup group = new
ThreadGroup("Print Group"); new Thread(group, ThreadGroupDemo::print, "t1"
).start();new Thread(group, ThreadGroupDemo::print, "t2").start();
group.list(); } }
 

未捕获异常处理器


  线程的run()不能抛出任何被检测的异常【因为Runnable接口中定义的run()没有抛出异常,所以重写run()时,不允许抛出异常,可以使用try-catch捕获异常】。但是,如果不被检测的异常没有使用try-catch处理,发生异常时会导致线程死亡。(比如下面这个例子,控制台并没有输出“Endind?”)
public class UncaughtExceptionDemo implements Runnable{ @Override public void
run() {int i = 1/0; System.out.println("Endind?"); } public static void
main(String[] args) { ExecutorService service= Executors.newFixedThreadPool(1);
service.execute(new UncaughtExceptionDemo()); } } /* log: ... Exception in
thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero at
concurrency.attributes.UncaughtExceptionDemo.run(UncaughtExceptionDemo.java:10)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)*/
  而且,在run中手动抛出了一个运行时异常,在main中使用try-catch处理异常,并未生效。(如下例,控制台并未输出"Current thread
occurs exception.")
public class UncaughtExceptionDemo implements Runnable{ @Override public void
run() {int i = 1/0; } public static void main(String[] args) { try{
ExecutorService service= Executors.newFixedThreadPool(1); service.execute(new
UncaughtExceptionDemo()); }catch (RuntimeException e){ System.out.println(
"Current thread occurs exception."); } } } /* ... Exception in thread
"pool-1-thread-1" java.lang.ArithmeticException: / by zero at
concurrency.attributes.UncaughtExceptionDemo.run(UncaughtExceptionDemo.java:10)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)*/
  
那么,应该如何处理线程中抛出的异常呢?事实上,异常发生后,在线程死亡之前,异常会被传递到一个用于未捕获异常的处理器。可以使用该处理器来处理线程中抛出的异常。
import java.util.concurrent.ExecutorService; import
java.util.concurrent.Executors;public class ThreadExceptionResolve implements
Runnable{ @Overridepublic void run() { int i = 1/0; System.out.println("Endind?"
); }public static void main(String[] args) { //2. 为所有的线程设置“异常处理器”
Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler()); //
3. 创建并执行线程 ExecutorService service = Executors.newFixedThreadPool(1);
service.execute(new ThreadExceptionResolve()); } } //1. 定义符合线程异常处理器规范的“异常处理器” //
该处理器必须属于一个实现Thread.UncaughtExceptionHandler接口的类 class
MyUncaughtExceptionHandlerimplements Thread.UncaughtExceptionHandler { @Override
public void uncaughtException(Thread t, Throwable e) { System.out.println("The
acculation is error."); } } /* ... The acculation is error. */
  安装处理器的方式有两种:
可以使用Thread的静态方法setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler
eh)为所有线程设置默认处理器,也可以使用Thread的实例方法setUncaughtExceptionHandler(UncaughtExceptionHandler
eh)为摸一个线程设定处理器。如果线程没有安装处理器,此时的处理器就是该线程的ThreadGroup对象。
//为所有线程设置默认处理器 Thread.setDefaultUncaughtExceptionHandler(handler); //为指定线程设置处理器
Thread mainThread = Thread.currentThread();
mainThread.setUncaughtExceptionHandler(handler);