[CoreJava2AdvancedFeatures][多线程]1.4线程属性

1.4 线程属性

在下面一节中,我们将讨论线程的各种属性: 线程优先级、守护线程、线程组,以及处理未捕获异常的处理器

1.4.1 线程优先级

在Java程序设计语言中,每一个线程都有一个优先级。默认情况下,一个线程继承他父线程的优先级。一个线程的父线程就是启动它的那个线程。你可以通过 setPriority方法提高或降低任何一个线程的优先级,你可以将优先级设置为在 MIN_PRIORITY(在Thread类中定义为1)和MAX_PRIORITY(定义为10)之间的任何值。NORM_PRIORITY被定义为5。

无论何时,当线程调用器有机会去挑选一个新的线程时,他会优先考虑高优先级的线程。但是, 线程优先级是高度依赖系统的。当虚拟机依赖于宿主机平台的线程实现机制时,Java线程优先级就会被映射成宿主机平台上的优先级,宿主机平台的优先级级别在数量上可能和Java里的有些出入。

例如, Windows NT/XP有7个优先级级别。Java的某些优先级将会映射到相同的操作系统优先级上。在 sun为Linux提供的虚拟机中,线程优先级完全被忽略,所有线程都具有相同的优先级。

因此,最好将线程优先级看作线程调度器的一个参考因素。千万不要将程序构建为其功能的正确性依赖于优先级。

警告:如果你确实要使用优先级,你应该警惕初学者常犯的一个错误。urguo你有一些高优先级的线程很少发生阻塞,那么低优先级的线程可能就永远都运行不了。无论何时,当调度器决定挑选一个新的线程的时候,它都会首先在优先级高的线程中进行选择,即使这样会使低优先级的线程完全饿死也是如此。

API java.lang.Thread 1.0
  • void setPriority(int newPriority)设置线程的优先级。优先级必须在Thread.MIN_PRIORITY和Thread.MAX_PRIORITY之间。一般情况下,使用Thread.NORM_PRIORITY优先级。
  • static int MIN_PRIORITY 线程的最低优先级,值为1。
  • static int MAX_PRIORITY 线程的最高优先级,值为10。
  • static int NORM_PRIORITY 线程的默认优先级,值为5。
  • static void yield() 导致当前执行线程进入让步状态。如果有优先级不低于他的其他可运行线程存在,那么这些线程接下来就会被调度。请注意,这是一个静态方法。
  1.  
 
1.4.2 守护线程

你可以通过调用

t.setDaemon(true);

将线程转变成一个守护线程。这样的线程并没有什么神奇的地方。一个守护线程的唯一作用就是为其他线程提供服务。计时器线程就是一个例子,他定是发送“时间嘀嗒”信号给其他线程。当只剩下守护线程的时,虚拟机就退出了,因为如果剩下的线程都是守护线程,就没有继续运行程序的必要了。

API java.lang.Thread 1.0

  • void setDaemon(boolean isDaemon) 将线程标记为守护线程或用户线程。这个方法必须在线程开始执行之前调用。
  1. 1.4.3 线程租

    某些程序只有很少的线程。如果将它们按照功能归类将很有用。以一个Internet浏览器为例。如果大量线程正试图从服务器上获取图片,此时用户点击Stop按钮来中断当前页面的载入,那么应该有很方便的方法同时中断所有这些线程。Java程序设计语言允许你创建线程租,这样就可以同时对一组线程进行操作。

    你可以用下面的构造器来创建线程租:

    String groupName = ...;
    ThreadGroup g = new ThreadGroup(groupName);

    ThreadGroup构造器中的字符串参数是用来表示该组的,它必须是唯一的。然后你可以添加线程到这个组中,方法是在线程的构造器中指定线程组。

    Thread t = new Thread(g,threadName);

    要查明某个特定线程组中是否有线程仍然处于可运行状态,应该使用activeCount方法。

    if(g.activeCount == 0)
    {
      // all threads in the group g have stopped.
    }

    要中断一个线程组中所有线程,只需要在组对象上调用interrupt方法

    g.interrupt(); //interrupt all threads in group g

    但是,executor可以使你在不使用线程组的情况下完成相同的任务。[关注:线程和Swing]

    线程组可以有子线程组。默认情况下,一个新建的线程组是当前线程组的子线程组。但是,你可以在构造器中明确地给出父线程组的名字(见API说明)。像activeCount和interrupt这样的方法引用的是本组和所有子组中的线程。

    API java.lang.Thread 1.0
    • Thread(ThreadGroup g, String name) 创建一个属于给定ThreadGroup的新Thread。参数:g —— 新线程所属的线程组;name —— 新线程的名字
    • ThreadGroup getThreadGroup() 返回该线程所在的线程组。
    1.  
    API java.lang.ThreadGroup 1.0

    • ThreadGroup(String name) 创建一个新的ThreadGroup。它的父线程组是当前线程所在的组。参数:name——新线程组的名字;;
    • ThreadGroup(ThreadGroup parent, String name) 创建一个新的ThreadGroup。参数:parent——新线程组所属的父线程组;name——新线程组的名字
    • int activeCount()返回线程组中活线程数的上界;
    • int enumerate(Thread[] list) 得到线程组中所有活线程的引用。你可以使用activeCount方法得到这个数组的上界;这个方法返回放入数组的线程数量。如果数组长度太短(假设因为调用activeCount之后又产生了更多的线程),那么就会插入适量的线程。参数:list——被填入线程引用的数组;
    • ThreadGroup getParent() 得到这个线程组的父线程组;
    • void interrupt() 中断这个线程组和他的子线程组中的所有线程。
1.4.4 未捕获异常处理器

线程的run方法不能抛出任何被检查的异常,但是不被检查的异常可以导致线程终止。如果出现这种情况,线程就死亡了。

然而,并不需要任何catch子句来处理可以被传播的异常。在线程死亡前,异常将被传地给未捕获异常处理器来处理。

处理器必须从属于实现了Thread.UncaughtExceptionHandler接口的类。这个接口只有一个方法。
  • void uncaughtException(Thread t, Throwable e)
  1.  
对于JDK 5.0,你可以用setUncaughtException方法来为任何一个线程安装一个处理器。你也可以通过Thread类的静态方法setDefaultUncaughtExceptionHandler为所有线程安装一个默认的处理器。替换处理器(replacement handler)可以使用日志API来将未捕获异常的报告写进日志文件中。

如果你没有安装默认处理器,那么默认的处理器就是null。但是,如果你没有为一个单独的线程安装处理器,此时的处理器就是线程的ThreadGroup对象。

ThreadGroup类实现了Thread.UncaughtExceptionHandler接口。它的uncaughtException方法作如下操作:
1)如果该线程组有父线程组,则调用父线程组的uncaughtException方法。
2)否则,如果Thread.getDefaultExceptionHandler方法返回一个非null的处理器,则调用该处理器。
3)否则,如果Throwable是一个ThreadDeath实例,则什么都不做;
4)否则,线程的名字和Throwable的堆栈总计将被输出到System.err上。
堆栈踪迹你肯定在自己的程序中多次看到过。

注意:在JDK5.0之前,你不能为每个线程都安装一个未捕获异常处理器,你也不能指定默认处理器。想要安装一个处理器,你需要继承ThreadGroup类,并重载uncaughtException方法。

API java.lang.Thread 1.0

  • static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler handler) 5.0
  • static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() 5.0
  1.  
      设置未捕获异常的默认处理器

  • void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler handler) 5.0
  • Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() 5.0
  1.  
      设置未捕获异常的处理器。如果处理器没有安装,则将线程组对象作为处理器。

API java.lang.Thread.UncaughtExceptionHandler 5.0

  • void uncaunghtException(Thread t, Throwable e) 定义该方法是为了在线程因为一个未捕获异常而终止时,将客户报告记录到日志中。参数:t——因为一个未捕获异常而终止的线程;e——未捕获的异常对象。
  1.  
API java.lang.ThreadGroup 5.0

  • void uncaughtException(Thread t, Throwable e)
  1.  
如果有父线程组的话,则调用父线程组的这个方法,或者如果Thread类有默认处理器的话,则调用该处理器;否则,在标准出错流上输出堆栈踪迹。(但是,如果e是一个ThreadDeath对象,那么堆栈踪迹是被禁用的。ThreadDeath对象是由stop方法产生的,不过stop方法已经被弃用了。)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值