Thread类的核心方法
JDK实现多线程编程的方式
-
继承Thread类
-
实现Runnable接口
Thread的主要方法
currentThread()
返回代码段正在被哪个线程调用的信息isAlive()
判断当前的线程是否处于活动状态sleep()
在指定的毫秒数内让当前”正在执行的线程“休眠(暂停执行)getId()
取得线程的唯一标识
线程退出
线程退出的方法
- 线程正常退出
stop()
方法强行终止线程,但是会导致不可预料的结果(数据集修改一半等),与resume都是作废过期的方法- 强制停止线程,立即停止;
- 该方法时不安全的(unsafe),会导致数据不一致的问题;
- 该方法可能抛出
java.lang.ThreadDeath
,因为强制让线程停止可能使得一些清理工作无法完成;
- 使用
interrupt()
方法中断线程(该方法只是断了一个退出的断点,但线程不一定会及时的退出)- 假设当线程处理休眠状态(调用了
sleep()
方法),调用该方法会抛出异常java.lang.InterruptedException
异常;
- 假设当线程处理休眠状态(调用了
判断线程是否是停止状态
-
this.interrupted()
测试当前线程是否已经中断- 静态方法,测试当前线程是否已经打了中断的标识
- 假设当前的线程是调用了
this.interrupt()
之后,调用一次之后,会将线程中的中断标识移除,即第一次会得到true,第二次调用的时候获得到false
-
this.isInterrupted()
测试线程是否已经中断-
成员方法,可以测试某个具体线程是否被中断
-
该方法不会移除中断标识,所以只要某个线程被中断过,那调用该接口则一直返回true
-
利用
this.isInterrupted()
和return
可以实现让线程即时退出,当调用了this.interrupt()
则通过逻辑保证让线程能够及时的退出,范例:for (条件) { if (this.isInterrupted()) { return; } }
-
线程暂停
线程暂停的方法
suspend()
可以暂停线程执行resume()
可以恢复线程执行
suspend()和resume()的缺点
独占
suspend()
和resume()
需要搭配使用,如果没有配套使用,当使用了suspend()
在暂停了线程的执行,那没有调用resume()
线程会一直休眠下去;
如果这个时候刚好在某个同步代码块中使用了suspend()
,那么这个同步代码块的资源会被永久占用
不同步
使用suspend()
和resume()
方法容易出现因为线程暂停而导致的脏数据问题(即无法保证suspend()
之前的业务操作回滚或者原子)
让出CPU资源
yield()
的作用是让出当前的CPU资源,将CPU资源让给其他的线程;一次只让一个时钟周期,可能在当前时钟周期的前中后
线程的优先级
线程的优先级
- 优先级越高,则获取的CPU资源相对越多
- Java中划分1-10这10个线程优先级
优先级的继承性
当设置了A线程的优先级,然后由A线程启动了B线程,那么B线程会继承A线程的优先级;
优先级的规则性
不关代码的顺序,设置了较高的优先级的线程理论上获取CPU时间的概率会比其他线程高;
优先级具有随机性
设置了优先级,只是保证在理论情况下优先级高的会获得比较多的CPU时间,尽量安排多的CPU时间给高优先级线程,但是不能保证一定每次都分配足够多的CPU时间给到对应线程;即不一定每次高优先级的线程都比低优先级的线程先执行完;
守护线程
Java中有两种线程
- 守护线程(通过
setDaemon(true)
的方式设置) - 非守护线程
守护线程的生命周期
只要有一个非守护线程的存在,守护线程会生存(最著名的就是GC线程),当所有的非守护线程都退出了,那么守护线程也就退出了