`

Java中的多线程学习一:线程的状态和属性

阅读更多
------摘自高人
为了使CPU的时间利用率更高,就有了多进程和多线程机制。如果是单个CPU,那么其实在微观中,还是一次执行一个线程,但是在宏观中,由于CPU的速度很快,就给了我们并发的感觉。



在Java中,实现多线程的类是 Thread 类。定义Thread对象有两种方法,一种是直接继承Thread,另一种是实现Runable接口。两者都需要写 run 方法。而且,无论是哪一种方法,生成的线程都是 Thread。也就是说,其实线程类只有一种,那就是Thread。



线程有线程自己的特性,多线程提高了CPU利用率的同时,也带来了一些问题。因此,在学习多线程,其实就是学习多线程编程多带来哪些问题,以及如何去解决这些问题,使得多线程能够按照我们的意愿来执行。



首先,线程有自己的状态,就像水也有自己的状态一样。水有气态,固态和液态;线程也有自己的状态,除了新建和死亡状态,就有 等待/阻塞 、准备 、和运行 状态。 同样的,这些状态可以转换。线程个状态的转换是:准备可以进入运行,运行也可以进入准备;运行还可以进入等待/阻塞;但是等待/阻塞不能进入运行,等待/阻塞可以进入准备状态。



知道了线程有这些状态,再加上控制线程的函数,我们就可以控制线程了,这就叫作线程的调度。



•新建 :就是利用Thread的构造函数定义一个线程,从此,线程的生命开始了。
•准备 :当执行了Thread中的strat方法,及使得线程进入准备状态,随时可以进入运行状态。
•运行 :当操作系统的调度器把CPU分给了这个线程,这个线程就进入了运行状态,也就是执行我们在线程中定义的run方法里面的内容。
•等待/阻塞 :

1.当一个线程的继续执行需要一个条件,但是该条件还不成熟,需要调度器来通知。而等待调度器发出通知的这段时间内,线程就进入了等待状态。
2.当一个线程访问一个资源的时候,这个资源正被另外的线程访问,而这个资源是加了锁的,之允许一个线程访问。这时候,线程就进入了阻塞状态。
•死亡:当线程的run方法运行完之后,线程死亡,这是正常死亡;当线程方发生异常而没有捕获时,也会死亡,这是非正常死亡。不管是正常死亡还是非正常死亡,都是死亡


线程除了有状态之外,还有自己的属性,这是很自然的,每个对象都有自己的属性。下面是一些重要属性:



•每个线程都有自己的优先级 。Java中的线程有10个优先级。但是结合操作系统来说,每个操作系统的线程优先级的数量各不相同。所以,Java提供了三个常量,分别是MIN_PRIORITY,NORM_PRIORITY,MAX_PRIORITY。
•守护属性 :如果线程被标志为守护属性,那么这个线程就是守护线程 。守护线程不能阻止程序的退出,只要没有主线程,程序就结束,而不管守护线程的运行状态。所以,我们一般不在守护线程中做一些主要工作。
设置线程的守护属性函数为:setDaemon(true)

•未捕获的异常处理器 。前面说了,如果线程抛出的异常没有被捕获,线程就会死亡。这就意味着,在设计线程时,要重视捕获异常。但是,如果没有捕获异常,或者出现了一个异常不到的异常,是不是线程就马上死亡呢?当然不是。
线程有一个重要的属性,就是未捕获的异常处理器 。
使用这个方法设置:setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

如果设置了这个属性,就表示如果有异常没有被捕获,那么就会启动这个处理器来处理这个异常,这样,就加强了我们都线程的处理能力。

这个方法中的传入参数:Thread.UncaughtExceptionHandler是个什么东西呢?

原来,UncaughtExceptionHandler是一个接口。在JDK中了解到:里面只有一个方法需要实现,即unCaughtException(Thread t, Throwalbe e)。

于是,如果在线程中有未被检测的异常中抛出时,线程就会自己查找自己的这个属性,也就是调用getUncaughtExceptionHandler。得到UncaughtExceptionHandler之后,再把该线程和抛出的异常传到这个处理器的unCaughtException方法中,进行异常处理。

因此,我们就可以自己制作线程的未捕获的异常处理器,也就是只要实现UncaughtExceptionHandler接口即可。

可是,我们必须为每个线程都设置这个为捕获的异常处理器属性,是不是太麻烦呢?所以,Java又帮了我们一个忙。

如果我们忘了为每个线程设置UncaughtExceptionHandler的时候,是不是线程抛出为捕获的异常时,就会死亡呢?答案是否定的。当线程抛出未捕获的异常时,而线程又没有设置处理器时,怎么办呢?

这时候,那么这时候的为捕获的异常处理器就变成了ThreadGroup,就是线程组(什么是ThreadGroup,等会再说)。因为线程组实现了UncaughtExceptionHandler。所以,ThreadGroup中也有uncaughtException方法,所以,也可以使用这个ThreadGroup作为处理器,

如果调用了ThreadGroup中的uncaughtException,那么会发生什么?

首先,会查看这个ThreadGroup有没有父线程组,如果有,则调用父线程组的uncaguhtException方法
否则,则使用全局的线程默认未捕获的异常处理器。
如果全局的线程默认为捕获异常处理器没有定义。再看该线程没有捕获的异常是不是ThreadDeath的一个实例,如果是,则设么都不做。
如果不是ThreadDeath,错误信息会被输出到System.err上。

那么,如何设置线程的全局默认为捕获异常处理器呢?

调用Thread的一个静态方法:
Thread.sedDeafaultUncaughtExceptionHandler(UncaughtExceptionHandler eh)

至此,线程对为捕获异常的处理的过程就是这样:


1.找出线程自己的处理器
2.如果找不到线程自己的处理器,则把线程所在的线程组当作处理器,主要是找到线程组中的uncaughtException方法。
3.如果找不到此方法,则找到此线程组所属的父线程组的这个方法。
4.如果还是找不到,就找线程全局默认的未捕获的异常处理器。
5.如果再不行,就看看这个线程没有捕获的异常是不是ThreadDeath,如果是,就什么都不做
      如果不是,就在System.err中输出错误信息。


那么,线程组又是什么东东呢?说白了,就是线程的一个集合。在Java中,只有一个默认的线程组,如果需要其他的线程组,就需要自己创建。除了默认 的线程组,其他的线程组都需要有一个父线程组。也就是说,Java中的线程组是树形结构的。



Java核心技术卷 写道

“但是从Java SE 5.0起引入了更好的特性用于线程集合的操作,不要在自己的程序中使用线程组。”



所以,对线程组的研究就暂告一段落了

分享到:
评论

相关推荐

    学习Java多线程之线程定义、状态和属性

    主要为大家详细介绍了Java多线程之线程定义、状态和属性,感兴趣的小伙伴们可以参考一下

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    对Java语言的每个语法都提供了一个或多个例程讲解 大量使用流程图表示程序的执行过程,使用结构图表示程序的内部状态 每章最后都给出了典型的练习题,让读者及时练习,巩固提高,并提供了参考答案 目录 第1篇 ...

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    对Java语言的每个语法都提供了一个或多个例程讲解 大量使用流程图表示程序的执行过程,使用结构图表示程序的内部状态 每章最后都给出了典型的练习题,让读者及时练习,巩固提高,并提供了参考答案 目录 第1篇 ...

    JAVA_API1.6文档(中文)

    java.awt.dnd Drag 和 Drop 是一种直接操作动作,在许多图形用户界面系统中都会遇到它,它提供了一种机制,能够在两个与 GUI 中显示元素逻辑相关的实体之间传输信息。 java.awt.event 提供处理由 AWT 组件所激发的...

    Java开发技术大全(500个源代码).

    ThreadImRunnable.java 继承Runnable接口实现多线程 mulThread.java 创建多个线程对象的类 demoJoin.java 演示使用join()以确保主线程最后结束 clicker.java 一个计数用的线程类 demoPri.java 调用上面这个类...

    Java清华教程.rar

     ■ 多线程程序设计,进程和线程的联系和区别,多线程程序设计的一般方法,线程的生命周期,线程状态的控制,多线程的互斥和同步;  ■ Java语言的网络编程技术和应用,Socket程序设计,Client/Server程序设计; ...

    JAVA上百实例源码以及开源项目源代码

     Java实现HTTP连接与浏览,Java源码下载,输入html文件地址或网址,显示页面和HTML源文件,一步步的实现过程请下载本实例的Java源码,代码中包括丰富的注释,对学习有帮助。 Java实现的FTP连接与数据浏览程序 1个...

    java源码包2

     Java实现HTTP连接与浏览,Java源码下载,输入html文件地址或网址,显示页面和HTML源文件,一步步的实现过程请下载本实例的Java源码,代码中包括丰富的注释,对学习有帮助。 Java实现的FTP连接与数据浏览程序 1个...

    java源码包---java 源码 大量 实例

     Java实现HTTP连接与浏览,Java源码下载,输入html文件地址或网址,显示页面和HTML源文件,一步步的实现过程请下载本实例的Java源码,代码中包括丰富的注释,对学习有帮助。 Java实现的FTP连接与数据浏览程序 1个...

    清华大学java教程

     ■ 多线程程序设计,进程和线程的联系和区别,多线程程序设计的一般方法,线程的生命周期,线程状态的控制,多线程的互斥和同步;  ■ Java语言的网络编程技术和应用,Socket程序设计,Client/Server程序设计; ...

    JAVA清华教程 详细

     ■ 多线程程序设计,进程和线程的联系和区别,多线程程序设计的一般方法,线程的生命周期,线程状态的控制,多线程的互斥和同步;  ■ Java语言的网络编程技术和应用,Socket程序设计,Client/Server程序设计; ...

    JAVA上百实例源码以及开源项目

     Java实现HTTP连接与浏览,Java源码下载,输入html文件地址或网址,显示页面和HTML源文件,一步步的实现过程请下载本实例的Java源码,代码中包括丰富的注释,对学习有帮助。 Java实现的FTP连接与数据浏览程序 1个...

    java 面试题 总结

    与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。...

    Java 1.6 API 中文 New

    java.awt.dnd Drag 和 Drop 是一种直接操作动作,在许多图形用户界面系统中都会遇到它,它提供了一种机制,能够在两个与 GUI 中显示元素逻辑相关的实体之间传输信息。 java.awt.event 提供处理由 AWT 组件所激发的...

    JAVA2核心技术(中文的PDF).part3.rar

    本书是Java 2技术权威指南,全面覆盖Java 2技术的高级主题,包括:多线程、集合框架、网络API、数据库编程、分布式对象等,深入探究了Swing、Java 2D API、JavaBean、Java安全模式、XML、注释、元数据等主题,同时...

    [清华大学]JAVA教程

     ■ 多线程程序设计,进程和线程的联系和区别,多线程程序设计的一般方法,线程的生命周期,线程状态的控制,多线程的互斥和同步;  ■ Java语言的网络编程技术和应用,Socket程序设计,Client/Server程序设计; ...

    java源码包4

     Java实现HTTP连接与浏览,Java源码下载,输入html文件地址或网址,显示页面和HTML源文件,一步步的实现过程请下载本实例的Java源码,代码中包括丰富的注释,对学习有帮助。 Java实现的FTP连接与数据浏览程序 1个...

    JAVA面试题最全集

    谈谈java多线程 23.谈谈文件加密技术 24.软件开发生命周期 25.路由协议种类及特点 26.java的awt和swing组件的GUI设计的关键 27.对于java流的认识 28.简单描述一下awt与swing区别。 29.简述java编程中事件处理...

    java源码包3

     Java实现HTTP连接与浏览,Java源码下载,输入html文件地址或网址,显示页面和HTML源文件,一步步的实现过程请下载本实例的Java源码,代码中包括丰富的注释,对学习有帮助。 Java实现的FTP连接与数据浏览程序 1个...

Global site tag (gtag.js) - Google Analytics