在Java中,实现多线程的类是 Thread 类。
定义Thread对象有两种方法,一种是直接继承Thread,另一种是实现Runable接口。两者都需要写 run 方法。
而且,无论是哪一种方法,生成的线程都是 Thread。也就是说,其实线程类只有一种,那就是Thread。
线程也有自己的状态,除了新建,就绪,运行,等待/阻塞,死亡。
这些状态可以转换。线程个状态的转换是:就绪可以进入运行,运行也可以进入就绪;运行还可以进入等待/阻塞;
但是等待/阻塞不能进入运行,等待/阻塞可以进入就绪状态。
# 新建 :就是利用Thread的构造函数定义一个线程,从此,线程的生命开始了。
# 就绪 :当执行了Thread中的strat方法,及使得线程进入就绪状态,随时可以进入运行状态。
# 运行 :当操作系统的调度器把CPU分给了这个线程,这个线程就进入了运行状态,
也就是执行我们在线程中定义的run方法里面的内容。
# 等待/阻塞 :
1. 当一个线程的继续执行需要一个条件,但是该条件还不成熟,需要调度器来通知。
而等待调度器发出通知的这段时间内,线程就进入了等待状态。
2. 当一个线程访问一个资源的时候,这个资源正被另外的线程访问,而这个资源是加了锁的,
之允许一个线程访问。这时候,线程就进入了阻塞状态。
# 死亡:当线程的run方法运行完之后,线程死亡,这是正常死亡;
当线程方发生异常而没有捕获时,也会死亡,这是非正常死亡。
不管是正常死亡还是非正常死亡,都是死亡
下面是一些重要属性:
* 优先级:每个线程都有自己的优先级 。
Java中的线程有10个优先级。但是结合操作系统来说,每个操作系统的线程优先级的数量各不相同。
所以,Java提供了三个常量,分别是MIN_PRIORITY,NORM_PRIORITY,MAX_PRIORITY。
* 守护属性 :如果线程被标志为守护属性,那么这个线程就是守护线程 。
守护线程不能阻止程序(进程)的退出,只要没有主线程,程序就结束,
而不管守护线程的运行状态。所以,我们一般不在守护线程中做一些主要工作。
设置线程的守护属性函数为:setDaemon(true)
* 异常处理:如果线程抛出的异常没有被捕获,线程就会死亡。这就意味着,在设计线程时,要重视捕获异常。
但是,如果没有捕获异常,或者出现了一个异常没有捕捉到,是不是线程就马上死亡呢?
当然不是。线程有一个重要的属性,就是未捕获的异常处理器 。
使用这个方法设置:setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
如果设置了这个属性,就表示如果有异常没有被捕获,那么就会启动这个处理器来处理这个异常,
这样,就加强了我们都线程的处理能力。
UncaughtExceptionHandler是一个接口,我们需要实现unCaughtException(Thread t, Throwalbe e)方法。
如果我们忘了为每个线程设置UncaughtExceptionHandler的时候,是不是线程抛出为捕获的异常时,就会死亡呢?
答案是否定的。当线程抛出未捕获的异常时,而线程又没有设置处理器时,怎么办呢?
这时候,那么这时候的为捕获的异常处理器就变成了ThreadGroup,就是线程组(什么是ThreadGroup,等会再说)。
因为线程组实现了 UncaughtExceptionHandler。所以,ThreadGroup中也有uncaughtException方法,
所以,也可以使用这个 ThreadGroup作为处理器。
如果调用了ThreadGroup中的uncaughtException,那么会发生什么?
首先,会查看这个ThreadGroup有没有父线程组,如果有,则调用父线程组的uncaguhtException方法
否则,则使用全局的线程默认未捕获的异常处理器。
如果全局的线程默认为捕获异常处理器没有定义。再看该线程没有捕获的异常是不是ThreadDeath的一个实例,
如果是,则设么都不做。
如果不是ThreadDeath,错误信息会被输出到System.err上。
那么,如何设置线程的全局默认为捕获异常处理器呢?
调用Thread的一个静态方法:
Thread.sedDeafaultUncaughtExceptionHandler(UncaughtExceptionHandler eh)
至此,线程对为捕获异常的处理的过程就是这样:
- 找出线程自己的处理器
- 如果找不到线程自己的处理器,则把线程所在的线程组当作处理器,主要是找到线程组中的uncaughtException方法。
- 如果找不到此方法,则找到此线程组所属的父线程组的这个方法。
- 如果还是找不到,就找线程全局默认的未捕获的异常处理器。
- 如果再不行,就看看这个线程没有捕获的异常是不是ThreadDeath,如果是,就什么都不做, 如果不是,就在System.err中输出错误信息
分享到:
相关推荐
Java线程是并发编程的核心部分,它允许程序在同一时间执行多个独立的任务,从而提高系统效率和响应速度。本文将深入探讨Java线程的概念、生命周期、实现方式以及相关的同步机制。 首先,理解线程的基本概念至关重要...
以上是对"Java多线程详解"主题的详细阐述,涵盖了Java多线程的基本概念、实现方式、线程控制、线程池、并发集合、线程间通信以及并发编程中常见的问题和解决方案。学习和熟练掌握这些内容对于开发高效的多线程Java...
Java提供了ExecutorService和ThreadPoolExecutor类来管理线程,创建线程池可以有效控制并发线程的数量,减少线程的创建和销毁开销。线程池的基本使用如下: ```java ExecutorService executor = Executors....
### Java多线程详解:深度探索Java线程机制 #### 知识点一:线程与进程的区别 在深入探讨Java多线程之前,我们首先需要理解线程与进程的基本概念及其区别。进程是资源分配的基本单位,拥有独立的内存空间,而线程...
首先,Java线程的创建主要有两种方式:通过实现Runnable接口和继承Thread类。实现Runnable接口使得类可以与其他接口一起实现,而继承Thread类则限制了类的多继承性。在创建线程后,需要调用start()方法启动线程,而...
Java多线程详解 在Java编程中,多线程是一种重要的技术,它使得程序能够同时执行多个任务,提高系统的效率和响应性。本教程将详细讲解Java中的多线程概念,包括线程的创建、状态、同步以及高级主题,旨在帮助初学者...
### Java多线程编程详解:深入理解与实践 #### 一、理解多线程机制 多线程,作为现代编程语言的重要特性之一,允许在单一应用程序内并发执行多个任务,从而极大提升了程序的效率和响应速度。在Java中,多线程的...
Java的`Thread`类提供了控制线程的方法,如`start()`启动线程,`join()`等待线程结束,`sleep()`使线程暂停执行等。 3. **线程同步** 在多线程环境中,数据共享可能导致数据不一致,为了解决这个问题,Java提供了...
Java线程是并发编程的核心部分,它允许程序在同一时间执行多个任务,从而提高了系统的效率和资源利用率。在Java中,线程是通过`Thread`类或者实现`Runnable`接口来创建和管理的。 首先,我们要理解进程和线程的概念...
本书浅显易懂的介绍了JAVA线程相关的设计模式,通过程序范例和UML图示来一一解说,书中代码的重要部分加了标注以使读者更加容易理解,再加上图文并茂,对于初学者还是程序设计高手来说,这都是一本学习和认识JAVA...
Java线程具有创建、就绪、运行、阻塞和死亡五种状态。创建状态是指用new操作创建了一个Thread实例,但尚未调用start()方法;就绪状态是指线程可以运行,但CPU还未分配时间片;运行状态是指线程获得CPU时间片,正在...
Java线程有四种基本状态:新状态、可执行状态、阻塞状态和死亡状态。 1. **新状态**:线程对象已创建,但`start()`方法尚未被调用。 2. **可执行状态**:线程准备就绪,等待CPU时间片,一旦获得即可执行。 3. **...
Java的多线程机制是Java语言的一大特性,它允许程序同时执行多个任务,提升程序响应速度,优化资源利用率。在Java中,线程是程序执行的最小单位,一个进程可以包含多个线程,每个线程都有自己独立的生命周期,包括...
Java线程有10个优先级,`Thread.NORM_PRIORITY`是默认优先级,`Thread.MIN_PRIORITY`和`Thread.MAX_PRIORITY`分别是最低和最高优先级。优先级高的线程更有可能获得CPU时间片。 6. **线程池**: `java.util....
《Java线程 高清晰中文第二版》中文第二版(PDF) 前言 第一章 线程简介 Java术语 线程概述 为什么要使用线程? 总结 第二章 Java线程API 通过Thread类创建线程 使用Runable接口的线程 线程的生命周期 线程命名 ...
【JAVA基础】JAVA多线程编程详解 Java多线程编程是Java开发中不可或缺的一部分,它允许多个任务在同一时间并发执行,提高了程序的效率和响应性。在Java中,线程是程序中的执行流,每个线程都有独立的执行控制,由...