Thread类的详细介绍
Thread类简介
Thread
类是Java中实现多线程编程的基础类。本篇博客就来介绍下Thread
类的常用API和常见用法。
Thread
类常用的方法如下:
- Thread.activeCount():这个方法用于返回当前线程的线程组中活动线程的数量,返回的值只是一个估计值,因为当此方法遍历内部数据结构时,线程数可能会动态更改。)。
- Thread.checkAccess(): 检验当前正在执行的线程是否有权限修改thread的属性,这个方法我们一般不自己进行调用,Thread类的set方法在进行属性修改时都会先调用这个方法。
- Thread.currentThread():获取当前正在运行的线程。
- Thread.dumpStack():输出线程栈,一般在debug的时候调用。
- Thread.enumerate(Thread tarray[]):??使用场景。
- Thread.getAllStackTraces():获取系统中所有线程的线程栈信息。
- thread.getName():获取线程的名字。
- thread.getPriority():获取线程的优先级。
- thread.getStackTrace():获取堆栈信息。
- thread.getState():获取线程状态。
- thread.getThreadGroup():获取线程所在线程组。
- thread.interrupt():使得指定线程中断阻塞状态,并将阻塞标志位置为true。
- thread.interrupted():测试当前线程是否被中断。
- thread.isAlive():判断线程是否还存活着。
- thread.isDaemon():判断线程是否是守护线程。
- thread.join():在当前线程中加入指定线程,使得当前线程必须等待指定线程运行结束之后,才能结束。可以理解成线程插队、等待该线程终止。
- Thread.sleep(long):强制线程睡眠一段时间。
- thread.start():启动一个线程。
- thread.setName(name):设置线程的名字。
- thread.setPriority(priority):设置线程的优先级。
- thread.setDaemon(true):将指定线程设置为守护线程。
- thread.yield():使得当前线程退让出CPU资源,把CPU调度机会分配给同样线程优先级的线程。
- object.wait()、object.notify()、object.notifyAll():Object类提供的线程等待和线程唤醒方法。
还有Thread
类提供了功能丰富的构造函数,大家可以选合适的使用
示例代码
public class MyThread {public static void main(String[] args) {Thread thread = Thread.currentThread();//这个方法返回的是当前线程所在线程组以及这个线程组的子线程组内活动的线程数//这个值是一个估计值,所以这个方法的应用场景不大int activeCount = Thread.activeCount();System.out.println("当前系统中活动线程数["+activeCount+"]");//向标准错误输出流输出当前的线程栈,不会阻断程序的继续执行Thread.dumpStack();//获取所有线程栈信息Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();//获取类加载器ClassLoader contextClassLoader = thread.getContextClassLoader();//获取当前线程名字String threadName = thread.getName();System.out.println("current thread name["+threadName+"]");//获取当前线程IDlong threadId = thread.getId();System.out.println("current thread id["+threadId+"]");//获取当前线程的优先级,一共有1~10总共10个优先级,这个优先级并不是在//所有平台都生效的int priority = thread.getPriority();System.out.println("current thread priority["+priority+"]");StackTraceElement[] stackTrace = thread.getStackTrace();System.out.println("-------------stackTrace info--------------");for (int i = 0; i < stackTrace.length; i++) {StackTraceElement element = stackTrace[i];System.out.println("className:["+element.getClassName()+"]");System.out.println("fileName:["+element.getFileName()+"]");System.out.println("line nunber:["+element.getLineNumber()+"]");System.out.println("method name:["+element.getMethodName()+"]");System.out.println("is native method:["+element.isNativeMethod()+"]");System.out.println("------------------------------------------");}Thread.State state = thread.getState();System.out.println("thread state:["+state+"]");ThreadGroup threadGroup = thread.getThreadGroup();String threadGroupName = threadGroup.getName();System.out.println("thread group name:["+threadGroupName+"]");//线程睡眠,调用sleep方法会使得线程进入timed_waiting状态,如果线程已经//获得了锁资源,调用sleep方法是不会释放这个锁的Thread.sleep(2000,500);Thread.sleep(1000);TimeUnit.SECONDS.sleep(2);Thread thread1 = new Thread(new Runnable() {@SneakyThrows@Overridepublic void run() {TimeUnit.SECONDS.sleep(100);}});thread1.start();thread1.join(50);}}
守护线程#
守护线程可以理解为服务线程,他们的作用就是服务于其他用户线程。当系统中不存在其他用户线程时,这些守护线程也会自动消亡。比如JVM的垃圾清理线程就是守护线程。我们可以使用如下方法查看和设置线程是否是守护线程。
thread.isDaemon();
thread.setDaemon(true);
sleep方法
Thread类中有一个静态的sleep方法,当一个执行中的线程调用了Thread的sleep方法后,调用线程会暂时让出指定时间的执行权,也就是在这期间不参与CPU的调度,但是该线程所拥有的监视器资源,比如锁还是持有不让出的。指定的睡眠时间到了后该函数会正常返回,线程就处于就绪状态,然后参与CPU的调度,获取到CPU资源后就可以继续运行了。如果在睡眠期间其他线程调用了该线程的interrupt()方法中断了该线程,则该线程会在调用sleep方法的地方抛出InterruptedException异常而返回(进入waiting状态线程的interrupt方法被调用,则这个线程会抛出InterruptedException异常)。
join方法
开发过程中我们可能会有这样的需求:多个线程分别加载资源,等这些线程资源加载完毕之后对这些资源做统一汇总处理。join
方法就能实现类似的功能。
调用线程的join方法会使得调用线程进入waiting状态,直到被调用的线程执行结束,调用线程才会重新获得执行的机会。
public class MyThread {public static void main(String[] args) throws Exception {Thread thread1 = new Thread(new Runnable() {@SneakyThrows@Overridepublic void run() {TimeUnit.SECONDS.sleep(100);}});thread1.start();thread1.join();System.out.println("main thread end...");}}
上面的代码中,main线程调用了thread1的join方法,main线程会被挂起进入waiting状态,直到thread1执行完毕之后,main线程才有机会重新获得执行机会。另外,如果main线程的interrupt方法被其他线程调用,那么main线程调用的join方法会抛出InterruptedException
异常。
join方法还有一个重载方法,这个方法可以指定超时时间。
thread1.join(50);
如果thread1线程在50ms内还没执行完,main线程就可以重新获得执行机会。
yeild方法
线程调用yield方法(这个方法是Thread的静态方法)是在暗示让这个线程让出CPU资源,如果这个线程在执行一个CPU时间,已经执行到一半了,调用yield之后这个线程会放弃剩下的一半CPU时间回到就绪状态。但是需要注意的是线程可以完全忽略yield方法的调用,也就是yield方法并不是每次都调用成功的:
- 退让成功时,退让线程会由Running(运行)转为Runnable(就绪)状态。
- 退让了的线程,与其他同优先级级别的线程一样,同样有再次获取CPU使用权的机会。
中断
先贴上一段网友对线程中断的总结。
- 如果线程不处于阻塞状态,那么调用interrupt()方法仅仅是将[中断标志位]将被置为true;
- 如果当前线程处于blocked阻塞(因为调用wait、sleep和join造成的)状态时被interrupt了,那么[中断标志位]将被清除,也就是设置为false,并且收到一个InterruptedException异常。
- 如果当前线程处于blocked阻塞(因为NIO的InterruptibleChannel进行的I/O操作造成的)状态时被interrupt了,则会关闭channel,[中断标志位]将会被置为true,并且当前线程会收到一个ClosedByInterruptException异常。
- 如果当前线程处于blocked阻塞(因为NIO的Selector造成的)状态时被interrupt了,那么[中断标志位]将被置为true,然后当前线程会立即从选择器区域返回并返回值(可能为非零的值)。
需要说明的是:interrupt()方法并不是中断线程,而是中断阻塞状态,也就是将线程的[中断标志位]置为true。中断后线程将继续执行。
PS:事实上,interrupt方法只是改变目标线程的中断状态(interrupt status),而那些会抛出InterruptedException异常的方法,如wait、sleep、join等,都是在方法内部不断地检查中断状态的值。
几个中断方法对比:
- public static boolean interrupted():测试当前线程(这边要注意的是这个方法返回的是当前正在执行的线程的中断状态,注意和isInterrupted的区别)是否已经中断。线程的中断状态 由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false。
- public boolean isInterrupted():测试线程是否已经中断。线程的中断状态 不受该方法的影响,也就是说不清除中断标志。
public boolean isInterrupted() {//传递false表示不清除标志位return isInterrupted(false);}
- public void interrupt():中断线程,例如,当线程A运行时,线程B可以调用线程A的interrupt()方法来设置线程A的中断标志为true并立即返回。设置标志仅仅是设置标志,线程A实际并没有被中断,它会继续往下执行。如果线程A因为调用了wait系列函数、join方法或者sleep方法而被阻塞挂起,这时候若线程B调用线程A的interrupt()方法,线程A会在调用这些方法的地方抛出InterruptedException异常而返回。
当线程为了等待一些特定条件的到来时,一般会调用sleep函数、wait系列函数或者join()函数来阻塞挂起当前线程。比如一个线程调用了Thread. sleep(3000),那么调用线程会被阻塞,直到3s后才会从阻塞状态变为激活状态。但是有可能在3s内条件已被满足,如果一直等到3s后再返回有点浪费时间,这时候可以调用该线程的interrupt()方法,强制sleep方法抛出InterruptedException异常而返回,线程恢复到激活状态。
Thread类的详细介绍相关推荐
- 【并发编程】Thread类的详细介绍
本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. Thread类是Java中实现多线程编程的基础类.本篇博客就来介绍下Thread ...
- 路由 OSPF LSA介绍、1~7类LSA详细介绍
1.0.0 路由 OSPF LSA介绍.1~7类LSA详细介绍 OSPF LSA 链路状态通告( Link status announcement),作用于 向其它邻接OSPF路由器 传递拓扑信息与路 ...
- Java Scanner类的详细介绍(Java键盘输入)
Java Scanner类的详细介绍(Java键盘输入) 一.Scanner类的简单使用 二.Scanner类的详细介绍 1.判断输入数据类型 2.next()与nextLine()的区别 3.求多个 ...
- 【OSATE学习笔记】AADL语法介绍(二)软件类构建详细介绍
介绍 本文主要介绍AADL软件类组件Process.Thread.Thread Group.Data.Subprogram.Subprogram Group的功能和基本用法. 这些被称作进程.线程组和 ...
- java Condition类的详细介绍
一 .condition 介绍及demo Condition是在java 1.5中才出现的,它用来替代传统的Object的wait().notify()实现线程间的协作,相比使用Object的wait ...
- c++进阶---IO类的详细介绍(一)
IO类 c++为了更好的处理不同的种类的IO的操作,IO库中定义了庞大的类库来处理不同种类的IO操作,该类库组成如下图所示: 首先,我们先了解一下这个庞大的IO库各个类之间的关系. ios是最基本的父 ...
- C++——String类超详细介绍
(欢迎及时指正错误!谢谢) STL的含义:标准模板库 STL的内容: 容器:数据的仓库 算法:与数据结构相关的算法.通用的算法(和数据结构无关) 注:熟悉常用的算法 sort reverse 迭代器 ...
- java用scanner类_java中关于scanner类的详细介绍
1.Scanner的实现步骤 第一步:在有效代码的第一行,通过import导入Scanner类!import java.util.Scanner; 第二步:通过new关键字实例化一个Scanner对象 ...
- UML图:类图 --详细介绍
类图的概念 描述类.接口及它们之间关系的图,显示系统中各个类的静态结构 类图的元素 类 面向对象系统组织结构的核心 对一组具有相同属性.操作.关系和语义的对象的抽象 包括名称部分(Name).属性部分 ...
最新文章
- 改变mysql数据库用户的权限
- python【蓝桥杯vip练习题库】ALGO-141 P1102(学生信息)
- flot中文API(转载)
- 【PP】长交期计划(LTP)简介
- AVFoundation 简介
- Bash shell脚本练习(一)
- 昆仑通态触摸屏如何把参数由触摸屏传递到PLC_昆仑通态MCGS触摸屏如何连接Modsim32进行组态仿真...
- I;P : Leaderboards and Achievements
- 《软件需求分析》阅读笔记3
- 【2022版】 Kafka面试题整理(含答案解析)
- WEB应用之JSP+Servlet
- 解决Mac下应用“已损坏”或“将对您的电脑造成伤害”
- 鼠标右键没有新建选项怎么办
- GPU 共享内存地址映射方式
- 分享一个动态sql编写工具
- phpfilter的妙用
- 网络应用程序的通信视角
- Spring三大核心思想详解
- OCR目前的发展现状综述
- 网络舆情信息传播动态监测查询方法