您的位置 首页 java

Java高并发编程-Thread常用API详解(重点篇)

没有强大的理论支撑的代码,都是自娱自乐,架构师带你学习 多线程 的原理到实战项目中的高并发解决方案,闲暇之余,分享技术干货,和喜爱技术的coder们一起交流,互相学习进步

本次主要和大家分享Thread常用 api 原理,我们工作中经常会用到Thread的一些api,那么这些API的原理大家又是否知道呢?不常用的API有哪些,了解这些之后,相信可以写出更优质的代码,少走弯路,同时也是面试必考的

sleep方法,线程休眠

1. 介绍

sleep方法根据传入的指定时间,进行休眠,线程进入sleep状态,不会释放monitor锁的所有权( 面试考点

2. sleep构造

sleep是一个静态方法,包含两个重载方法,一个需要传入毫秒数,另一个既需要传入毫秒数也需要传入纳秒数

3. TimeUnit,使代码更优雅

JDK 1.5以后,JDK引入了枚举java.util.concurrent.TimeUnit,封装了sleep,

TimeUnit支持时间的拼接,比如1小时2分29秒87毫秒,sleep则需要繁琐的计算,并且代码可读性不高,如:

TimeUnit.HOURS.sleep(1);

TimeUnit.MINUTES.sleep(2);

TimeUnit.SECONDS.sleep(29);

TimeUnit.MILLISECONDS.sleep(87);

在以后的开发中,强烈建议大家使用TimeUnit代替sleep,因为sleep能做的事情,TimeUnit都能做

yield方法,资源让步

1. 介绍

yield方法,是 JNI 方法,底层C++实现,属于启发式的方法,提醒CPU调度器,愿意放弃当前CPU资源,值得注意的是,在CPU资源不紧张的情况下,会忽略这种提醒,笔者经过多次测试, yield 只是一个提示,并不能保证CPU调度器每次都能满足yield的提示

2. sleep与yield有什么差异呢?

(1) sleep会导致线程短暂的休眠,但是没有CPU时间片的消耗

(2) yield只是对CPU调度器的提示,如果CPU调度器没有忽略,使线程从RUNNING状态进入RUNNABLE状态,导致线程上下文切换,

(3) sleep使线程进入短暂的block,同时释放CPU资源

(4) 一个线程sleep另外一个线程调用 interrupt 会捕获到中断信号,而yield不会

setPriority / getPriority方法,线程优先级

1. 介绍

原则上 CPU 比较忙时,线程的优先级越高,可以获得更多的CPU时间片,CPU闲时,线程优先级基本被忽略,实际业务中不会显示的设置 线程 优先级,基本上都是使用默认线程优先级5,因为main函数的线程优先级是5,main所在线程派生的线程也默认为5,所以线程优先级不显示的指定时,与父线程的优先级一致,关于线程优先级,大家了解一下就好,不必深究

2. 源码

setPriority为设置线程优先级,getPriority为获取线程优先级,从源码中我们可以看到,线程优先级最大是10,最小是0,超出这个范围,则会报错IllegalArgumentException,如果设置的线程优先级超出当前组的线程优先级,以当前组的线程优先级为准

currentThread方法,获取当前线程

1. 介绍

Thread.currentThread()是JNI方法,返回当前线程引用

2. 获取线程ID

getId()方法是返回当前线程id,线程id在整个jvm中是自增的、唯一的,我们测试过程中,在main函数中创建了一个唯一的线程,打印出来线程id不等于0,也许会有疑问,线程id不是从0开始的吗?原因很简单, jvm 启动过程中开辟了很多线程,所以我们创建的线程不是从0开始

Interrupt 、isInterrupted、 Interrupted 方法,线程中断函数

1. 可中断方法有哪些呢?

导致线程阻塞的方法,都是可中断方法,wait、wait(long)、wait(long,int)、sleep(long)、sleep(long,init)、join()、join(long)、join(long,int)、interruptibleChannel的io操作、Selector的wakeup方法

2. Interrupt方法

Interrupt函数的作用是打断当前线程的阻塞状态,不是结束线程的生命周期,被打断的线程会跑出InterruptedException

一个线程的内部存在着interrupt flag标记,当一个线程被interrupt,flag的标记将会被清除,如果一个线程执行可中断方法被阻塞,再执行interrupt方法会擦除标记,将线程的标识复位,目的是为了不影响线程内其他方法执行

3. isInterrupted方法

isInterrupted是thread的成员方法,只是判断线程是否被中断,不会改变线程inerrupt标识

4. interrupted方法

Interrupted是 Thread 的一个静态方法,用于判断线程是否被打断,但是该方法会擦除线程的interrupt标识,interrupted和isInterrupted调用了同一个方法,关键在于入参:clearInterrupted,是否擦除interrupt标识

join方法

1. 介绍

join一个线程,会使当前线程进入阻塞,直到该线程生命周期结束,也就是主线程等待join的线程执行完成之后,才会执行,实际开发工作中,join非常实用,比如多线程处理业务,业务处理完成后,主线程汇总

关闭线程

在这里问大家一下,大家在实际工作中是如何关闭线程的呢?看完我介绍的,看看你是否正确地关闭了一个线程

1. 线程生命周期结束

线程生命周期执行完成

2. 捕获中断信号关闭线程

业务执行完成,中断线程,线程内方法通过捕获中断信号,结束线程生命周期,单要线程的interrupt有可能会被擦除,一般用于 心跳检测 等场景

3. volititle修饰的成员变量

这种方式最为实用,因为volititie修饰的变量是内存可见的

4. 抛出异常

线程执行单元不允许抛出check异常,不过可以封装成unchecked异常,如RuntimeException抛出异常结束线程生命周期

总结

以上主要讲了Thread的常用方法,以及哪些方法是可中断方法,如何中断线程,如何关闭线程,在实际的开发工作中,理解这些常用方法的原理,可以使自己的代码更优雅,科学,加油,猿人们,一个老程序员的祝福

文章来源:智云一二三科技

文章标题:Java高并发编程-Thread常用API详解(重点篇)

文章地址:https://www.zhihuclub.com/192512.shtml

关于作者: 智云科技

热门文章

网站地图