这篇文章计划讲一下整个Java线程的生命周期。
要了解一个线程,首先要从它的创建说起,然后是线程的执行以及线程与线程之间的交互,最后是线程的销毁。
一、线程的创建
线程的创建有四种方式:
1)继承Thread类创建线程
2)实现Runnable接口创建线程
3)使用Callable和Future创建线程
4)使用线程池例如用Executor框架
具体参见博客:线程创建的四种方式
二、线程的执行
线程的运行时状态一共有三种:就绪态、阻塞态和运行态,它们之间的状态转换关系如下图所示:
详细介绍参见博客:线程的生命周期
线程之间的交互参见以下博文:
线程基础 第一篇:线程的定义、状态、属性、简单实现线程
线程基础 第二篇:多线程之间的同步
线程基础 第三篇:多线程之间的通信
JAVA多线程之线程间的通信方式
三、线程的销毁
线程属于一次性消耗品,在执行完run()方法之后线程便会正常结束了,线程结束后便会销毁,不能再次start,只能重新建立新的线程对象,但有时run()方法是永远不会结束的。例如在程序中使用线程进行Socket监听请求,或是其他的需要循环处理的任务。在这种情况下,一般是将这些任务放在一个循环中,如while循环。当需要结束线程时,如何退出线程呢?
参见博文:Java结束线程的三种方法
Java垃圾回收无效线程吗?(这篇文章说的有点问题,线程不是由Java垃圾回收来销毁的,Java垃圾回收回收的是Java对象,而线程是一种系统资源,是由Java虚拟机负责释放的,关于Java垃圾回收,见下面一篇博文)
java多线程与并发(六)——java的垃圾回收机制
Java的结构之美【2】——销毁对象
四、引入线程池
在web开发中,服务器需要接受并处理请求,所以会为一个请求来分配一个线程来进行处理。如果每次请求都新创建一个线程的话实现起来非常简便,但是存在一个问题:如果并发的请求数量非常多,但每个线程执行的时间很短,这样就会频繁的创建和销毁线程,如此一来会大大降低系统的效率。可能出现服务器在为每个请求创建新线程和销毁线程上花费的时间和消耗的系统资源要比处理实际的用户请求的时间和资源更多。
那么有没有一种办法使执行完一个任务,并不被销毁,而是可以继续执行其他的任务呢?
参见博文:深入理解Java线程池:ThreadPoolExecutor
浅谈Java并发编程系列(六) —— 线程池的使用
五、问题
1、假如你只对线程和线程池有初步的了解,那么你认为线程池应该怎么使用呢?
比较符合直觉的线程池的使用方式应该是:1. 定义一个实现了Runnable的对象作为我们要执行的任务 2. 从线程池中取出一个线程对象 3. 用取出的线程对象来执行我们定义的任务 4.任务执行完毕后调用线程对象的close方法把线程对象放回线程池。
上面的步骤几乎就是我们在使用数据库连接池时的步骤,那么这个步骤对于线程池来说合适吗?
问题出在第2、3、4步,假如我们能够取得一个线程对象,那么我们能让这个线程对象执行我们定义的任务吗?通过上面的介绍,这种方式是不可行的。因为任务是在线程创建的时候指定的,当线程创建以后我们就不能修改线程执行的任务了。那么我们的线程池应该怎么实现呢?我们不能用这种主动的方式,而应该用被动的方式,把任务提交给线程池,让线程池为我们执行这个任务。这其中用到了生产者消费者模式。
参见博文:生产者消费者模式-Java实现
我们只负责任务的创建,而任务的消费交由线程池。我们是生产者,而线程池是消费者。
关于Java中线程池的详细设计,请参见博文:JAVA线程池原理详解一
浅谈Java并发编程系列(六) —— 线程池的使用
深入理解Java线程池:ThreadPoolExecutor
2、线程一旦创建并运行,如果线程中的代码抛出了异常应该如何处理?
参见博文:JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止
既然Java线程能设置统一的异常处理器,那么整个Java应用能不能捕获到未处理异常进行统一处理呢?
参见博文:java统一异常处理
Java线程详解
最新推荐文章于 2020-04-15 15:50:29 发布