目录
说明:这一系列博客内容摘自《Java核心技术 卷I》
一、什么是线程
线程和进程的区别联系,如何实现多线程:
https://blog.csdn.net/wyplj2015/article/details/78592659
二、线程状态
线程有6种状态:(Thread.State)
New(新创建) Runnable(可运行) Blocked(被阻塞)
Waiting(等待) Timed waiting(计时等待) Terminated(被终止)
可调用getState方法获得线程的当前状态。
1、新创建线程
当用new创建一个新线程时,该线程还没有开始运行,它的状态是new。
2、可运行线程
一旦调用start方法,线程处于runnable状态。
一个可运行的线程可能正在运行也可能没有运行。
3、被阻塞线程和等待线程
当线程处于被阻塞或等待状态时,它暂时不活动。它不运行任何代码且消耗最少的资源,直到线程调度器重新激活它。
阻塞状态:当一个线程试图获取一个内部的对象锁,而该锁被其他线程持有,该线程进入阻塞状态。当该锁被释放,且线程调度器允许本线程持有它时,该线程将变成非阻塞状态。
等待状态:当线程等待另一个线程通知调度器一个条件时,该线程进入等待状态。有几个方法有一个超时参数,调用它们导致线程进入计时等待(timed waiting)状态,这一状态保持到超时期满或者接收到适当的通知。(方法:Thread.sleep Object.wait Thread.join Lock.tryLock Condition.await)
ps:void join() 等待指定线程的终止
当一个线程被重新激活(例如,因超时期满或获得锁),调度器检查它是否具有比当前运行线程更高的优先级,如果是,则调度器从当前运行线程中选一个,剥夺其运行权,选择一个新的线程运行。
4、被终止的线程
线程被终止有两个原因:
因为run方法正常退出而自然死亡。
因为一个没有捕获的异常终止了run方法而意外死亡。
三、中断线程
没有可以强制线程终止的方法(stop方法已停用)。但可以使用interrupt方法来请求终止线程。
void interrupt() 向线程发送中断请求。线程的中断状态将被设置为true。
当在一个被阻塞的线程(调用sleep或wait)上调用interrupt方法时,会抛出Interrupted Exception异常,阻塞调用被异常中断。
当在中断状态被置位时调用sleep方法,它不会休眠。相反,它将清除这一状态,并抛出Interrupted Exception。所以,调用sleep方法时,一定要捕获异常(要处理,不要光catch而不处理,也可以直接throws)
static boolean interrupted() 静态方法。测试当前线程是否被中断。副作用:会将当前线程的中断状态重置为false。
boolean isInterrupted() 测试线程是否被中断。不改变线程的中断状态。
具体例子说明参考:https://www.cnblogs.com/lt132024/p/6438897.html
四、线程属性
1、线程优先级
Java中,每个线程都有一个优先级。默认情况下,一个线程继承它的父线程的优先级。
线程优先级高度依赖于系统,不要将程序构建为功能的正确性依赖于优先级。
ps:static void yield() 静态方法。导致当前线程处于让步状态。如果有其他的可运行线程具有至少与此线程同样高的优先级,那么这些线程接下来将会被调度。
2、守护线程
t.setDaemon将线程转换为守护线程(Daemon thread),这一方法必须在线程启动之前调用。
守护线程的唯一用途是为其他线程提供服务。当只剩下守护线程时,虚拟机就退出了。
守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至在一个操作的中间发生中断。
3、未捕获异常处理器
线程的run方法不能抛出任何被检测的异常(不能throws,只能try-catch处理,因为不论是Thread还是Runnable都没有定义抛出异常),但是,不被检测的异常(比如运行时异常,例如除数为0)会导致线程终止。
因此,要把这种异常交给一个用于未捕获异常的处理器。
该处理器必须属于一个实现Thread.UncaughtExceptionHandler接口的类,可以用setUncaughtExceptionHandler方法为任何线程安装一个处理器,也可以用Thread类的静态方法setDefaultUncaughtExceptionHandler为所有线程安装一个默认的处理器。
参考链接:https://www.cnblogs.com/brolanda/p/4725138.html
如果不为独立的线程安装处理器,此时的处理器就是该线程的ThreadGroup对象。
ThreadGroup类实现了Thread.UncaughtExceptionHandler接口,它的uncaughtException方法做如下操作:
(1)如果该线程组有父线程组,调用父线程组的uncaughtException方法
(2)否则,如果Thread.getDefaultExceptionHandler方法返回一个非空的处理器,则调用该处理器。
(3)否则,如果Throwable是ThreadDeath的一个实例,则什么都不做
(4)否则,将线程的名字和Throwable的栈踪迹输出到System.err上。
参考:《Java核心技术卷I》