为了使CPU的时间利用率更高,就有了多进程和多线程机制。如果是单个CPU,那么其实在微观中,还是一次执行一个线程,但是在宏观中,由于CPU的速度很快,就给了我们并发的感觉。
在Java中,实现多线程的类是 Thread 类。定义Thread对象有两种方法,一种是直接继承Thread,另一种是实现Runable接口。两者都需要写 run 方法。而且,无论是哪一种方法,生成的线程都是 Thread。也就是说,其实线程类只有一种,那就是Thread。
线程有线程自己的特性,多线程提高了CPU利用率的同时,也带来了一些问题。因此,在学习多线程,其实就是学习多线程编程多带来哪些问题,以及如何去解决这些问题,使得多线程能够按照我们的意愿来执行。
首先,线程有自己的状态,就像水也有自己的状态一样。水有气态,固态和液态;线程也有自己的状态,除了新建和死亡状态,就有 等待/阻塞
、准备
、和运行
状态。 同样的,这些状态可以转换。线程个状态的转换是:准备可以进入运行,运行也可以进入准备;运行还可以进入等待/阻塞;但是等待/阻塞不能进入运行,等待/阻塞可以进入准备状态。
知道了线程有这些状态,再加上控制线程的函数,我们就可以控制线程了,这就叫作线程的调度。
- 新建
:就是利用Thread的构造函数定义一个线程,从此,线程的生命开始了。
- 准备
:当执行了Thread中的strat方法,及使得线程进入准备状态,随时可以进入运行状态。
- 运行
:当操作系统的调度器把CPU分给了这个线程,这个线程就进入了运行状态,也就是执行我们在线程中定义的run方法里面的内容。
- 等待/阻塞
:
- 当一个线程的继续执行需要一个条件,但是该条件还不成熟,需要调度器来通知。而等待调度器发出通知的这段时间内,线程就进入了等待状态。
- 当一个线程访问一个资源的时候,这个资源正被另外的线程访问,而这个资源是加了锁的,之允许一个线程访问。这时候,线程就进入了阻塞状态。
- 死亡:当线程的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)
至此,线程对为捕获异常的处理的过程就是这样:
- 找出线程自己的处理器
- 如果找不到线程自己的处理器,则把线程所在的线程组当作处理器,主要是找到线程组中的uncaughtException方法。
- 如果找不到此方法,则找到此线程组所属的父线程组的这个方法。
- 如果还是找不到,就找线程全局默认的未捕获的异常处理器。
- 如果再不行,就看看这个线程没有捕获的异常是不是ThreadDeath,如果是,就什么都不做
如果不是,就在System.err中输出错误信息。
那么,线程组又是什么东东呢?说白了,就是线程的一个集合。在Java中,只有一个默认的线程组,如果需要其他的线程组,就需要自己创建。除了默认 的线程组,其他的线程组都需要有一个父线程组。也就是说,Java中的线程组是树形结构的。
Java核心技术卷 写道
“但是从Java SE 5.0起引入了更好的特性用于线程集合的操作,不要在自己的程序中使用线程组。”
所以,对线程组的研究就暂告一段落了
------------------
听者有心
原创
分享到:
相关推荐
在学习Java多线程的过程中,理解线程与进程的概念是非常基础且重要的一步。首先,进程是一个程序的执行实例,是操作系统资源分配的基本单位,具有独立的地址空间和运行状态。每个进程至少包含一个线程,我们称之为...
### JAVA编程高级-多线程编程 ...总之,Java中的多线程编程是一个非常重要的主题,对于提高程序的性能和响应速度有着不可替代的作用。掌握好Java中的多线程机制,可以帮助开发者更好地设计和实现高效的应用程序。
总之,“JAVA多线程游戏之简易飞机大战”项目展示了`JAVA`的多线程技术在游戏开发中的应用,同时也体现了`Swing`库的强大功能。通过学习这个项目,开发者不仅可以提升`JAVA`编程和多线程技能,还能理解如何设计一个...
标签中的"源码"提示我们可能会看到实际的Java代码示例,这对于学习和理解多线程编程以及Java与Oracle的交互非常有帮助。通过分析和研究这些代码,开发者能够掌握如何在实际项目中应用多线程技术,并理解如何有效利用...
本书“Java多线程编程实例”深入浅出地讲解了如何在Java环境中实现多线程操作,尽管出版时间较早,但其内容的经典性和实用性使其在现代开发中仍具有极高的参考价值。 首先,我们要理解Java中的线程是如何创建的。...
在Java多线程编程中,理解如何创建和管理线程是至关重要的。在这个经典例子中,我们看到两种创建线程的方式:通过继承`Thread`类和实现`Runnable`接口。 首先,我们创建了一个名为`ThreadUseExtends`的类,它直接...
总之,Java多线程技术结合分页读取策略能有效提升数据库操作的效率,但同时也需要关注并发控制、资源管理以及异常处理等多个方面的细节,确保程序的稳定性和效率。在实际开发中,应根据项目需求和资源限制,选择合适...
你可以通过运行这些示例来更好地理解和学习Java多线程的概念。例如,它可能包含一个继承`Thread`的类,一个实现`Runnable`的类,以及演示如何启动和管理这些线程的主程序。 总结,理解并熟练掌握Java中的多线程实现...
【Java 多线程学习详细总结...通过理解并熟练掌握这些Java多线程知识点,开发者可以编写出高效、安全的并发程序,解决复杂的并发问题。在实际开发中,应根据具体需求选择合适的线程同步机制,确保程序的稳定性和性能。
贪吃蛇游戏是一款经典的...通过对源码的深入分析,可以学习到Java多线程编程的具体实践,以及如何在实际项目中应用这些概念。此外,也可以了解到如何用Java实现基本的游戏逻辑,这对于初学者来说是一个很好的学习资源。
在Java编程中,多线程技术是实现并发执行任务的关键,尤其在开发高效能的应用程序时,如模拟电影院的购票系统。在这个系统中,我们利用Java的多线程特性来模拟多个用户同时购票的情况,确保系统的高并发处理能力。...
Java编程中的线程动画是一种利用多线程技术在图形用户界面(GUI)上实现动态效果的方法。线程是操作系统分配CPU时间的基本单元,Java通过提供...同时,不断学习和实践将帮助你更好地理解和掌握Java多线程编程的精髓。
### 一、JAVA多线程技术 JAVA的多线程技术是其并发处理能力的重要组成部分。多线程允许在同一时间处理多个任务,提高程序的执行效率和响应速度。在PC/PLC通信场景中,多线程可以分别负责数据接收、数据发送、错误...
总的来说,通过“JAVA多线程实验,字符移动、小球碰撞”这两个案例,我们可以学习到如何在Java中创建线程、实现线程间的通信和同步,以及如何有效地管理线程资源。这些知识对理解和编写高效的并发程序至关重要,是每...
【标题】:“自己用JAVA做的一个多线程文件服务器” ...通过学习这个项目,读者可以深入理解Java多线程编程、网络编程以及文件服务器的基本原理,同时也是一个很好的实践案例,帮助提升实际开发技能。
Java多线程断点下载文件是一种高效的文件下载方式,它允许在下载过程中暂停并从上次停止的地方继续,尤其适用于大文件下载。以下是实现这一功能的关键知识点: 1. **获取文件信息**: - 使用`java.net.URL`和`java...
在Java编程中,线程是并发编程的核心概念,允许程序同时执行多个任务,提高了系统资源的利用率和程序的响应速度。以下是对Java线程相关知识点的详细说明: 1. **线程的创建与执行** - 创建线程有两种方式:继承`...
本项目"java多线程模拟处理银行的实时转账交易"旨在通过多线程技术来模拟实现这一过程,确保程序的可扩展性和高效率。 首先,我们需要理解多线程的基本概念。线程是操作系统分配CPU时间片的基本单位,一个进程中...