[JavaEE] Thread类及其常见方法
创始人
2024-05-02 09:54:02
0


专栏简介: JavaEE从入门到进阶

题目来源: leetcode,牛客,剑指offer.

创作目标: 记录学习JavaEE学习历程

希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长.

学历代表过去,能力代表现在,学习能力代表未来! 


目录

1.Thread 的常见构造方法

2.Thread 的几个常见属性

3. 启动一个线程

4. 中断一个线程

5. 等待一个线程

6. 获取当前线程引用

7. 休眠当前线程


Thread 类是 JVM 用来管理线程的一个类 , 换句话说 , 每个线程都有唯一的 Thread类 与之关联.Thread 类的对象就是用来描述一个执行流的 , JVM 会将这些Thread对象组织起来 , 用于线程调度和线程管理.


 1.Thread 的常见构造方法

方法说明
Thread()创建线程对象
Thread(Runnable target)使用 Runnable 对象创建线程对象
Thread(String name)创建线程对象 , 并命名
Thread(Runnable target , String name)使用Runnable 对象创建线程对象 , 并命名
Thread(ThreadGroup group , Runnable target)

线程可以被用来分组管理 ,

分好的组即为线程组 , 目前了解即可.

给线程创建的对象命名是为了方便在各种调试工具中调试. 

class MyRunnable implements Runnable{@Overridepublic void run() {System.out.println("Hello Thread");}
}
public class ThreadDemo2 {public static void main(String[] args) {Thread t1 = new Thread();Thread t2 = new Thread("线程的名字");Thread t3 = new Thread(new MyRunnable());Thread t4 = new Thread(new MyRunnable() , "线程的名字");}
}

 2.Thread 的几个常见属性

属性获取方法
IDgetId()
名称getName()
状态getState()
优先级getPriority()
是否后台线程isDaemon()
是否存活isAlive()
是否被中断isInterrupted()
  • ID 是线程的唯一标识 , 不同线程不会重复.
  • 名称 在各种调试工具中用到.
  • 状态表示当前线程所处的一个情况.
  • 优先级高的线程 , 理论上来讲更容易被调度到.
  • 关于后台线程需要注意 , 后台线程的结束与否不会影响到进程.
  • 是否存活 , 通俗来讲就是 run() 是否结束了.
  • 关于是否中断 , 下面专门会讲.

3. 启动一个线程

之前我们以及知道 , 如何通过覆盖 run() 方法覆盖一个线程对象 , 但线程对象被创建出来并不意味着线程就开始运行了 .

  • 覆盖 run() 方法是提供给线程要做的事情的指令清单.
  • 创建线程对象可以认为是把张三 , 李四叫到一起.
  • 而调用 start() 方法才是喊了一声行动 , 线程才真正的执行起来.此时操作系统才会在底层创建一个线程.

 


 4. 中断一个线程

李四一旦进入工作状态 , 就会按照行动指南一直执行直到结束. 但有时出现突发状况 , 例如老板临时改变主意或者发现汇款对象是个骗子 , 这时就需要停止转账. 那么张三应该如何通知李四呢?这就涉及到中断线程的操作.

目前常见的有以下两种方式:

  • 1.通过共享标记来进行沟通.
  • 2.调用 Interrupt() 方法来通知.

示例一: 通过共享标记为来沟通.

在主线程中就可以随时通过 flag 变量的取值 , 来操作 t 线程是否结束 , 但这种方式有一个明显的缺点就是不能及时响应 , 例如while循环中的休眠时间较长就需要一直等待.

public class ThreadDemo2 {public static boolean flag = true;public static void main(String[] args) {Thread t = new Thread(()->{while (true){System.out.println("Hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});t.start();Thread.sleep(3000);//此时在主线程中就可以随时通过 flag 变量的取值 , 来操作 t 线程是否结束.flag = false;}
}

示例二: 调用 Interrupt() 方法来通知

currentThread() 是Thread类的静态方法 , 通过这个方法可以获取到当前线程 , 哪个线程调用这个方法哪个线程 , 就会得到哪个线程对象的引用.类似于 this. isInterrupted() 相当于上面例子中的标志位 , 为 true 表示终止 , 为 fasle 表示未被终止. t.interrupt() 就是终止线程.

Tips : 如果线程在 sleep 中休眠 , 此时调用 interrupt 就会出发 sleep 内部的异常(InterruptedException) , 导致sleep提前返回.

public static void main(String[] args) throws InterruptedException {Thread t = new Thread(()->{while (!Thread.currentThread().isInterrupted()){System.out.println("Hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();;}}});t.start();Thread.sleep(3000);t.interrupt();}

此时运行代码就会发现问题 , 明明抛出异常但进程还在执行.

 这时因为 interrupt 虽然会做两件事:

  • 1. 把线程内部的标志位 boolean 给设置成 true.
  • 2. 如果线程在进行 sleep , 就会触发异常并且把 sleep 唤醒.

但 sleep 被唤醒后 , 还会做一件事 , 把刚才设置的这个标志位 , 再设置成 false .(清空标记为) 可以形象的理解成 sleep 有"起床气". 为了解决这一问题 , 可以在catch语句后加 break .线程立即响应你的请求. 为什么唤醒 sleep 后要清空标志位呢? 这时为了把唤醒 sleep 后程序是否要终止的选择权交给程序员自己.


5. 等待一个线程

由于线程的执行是一个随机调度的过程 , 等待线程要做事情就是更好的控制线程的执行顺序.

方法说明
public void join();等待线程结束
public void join(long millis);等待线程结束 , 最多等millis毫秒
public void join(long millis , int nanos);同理 , 精度更高.

主线程等待 t 线程彻底执行完后再继续执行. 

 public static void main(String[] args) {Thread t = new Thread(()->{System.out.println("Hello thread");});t.start();System.out.println("join 之前");//此处的 join 就是让当前的 main() 线程来等待 t 线程的执行结束(等待 t 的run() 执行完)try {t.join();} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("join 之后");}

 

Tips: 如果开始执行 join 时 , t 已经结束了 , join将不会阻塞立即返回. 


6. 获取当前线程引用

方法说明
public static Thread currentThread();                                             返回当前线程对象的引用

 7. 休眠当前线程

方法说明
public static void sleep (long millis) throw InterruptedException休眠当前线程millis毫秒

线程休眠的本质是让这个线程不参与调度 , 在操作系统内核中 , 线程 A 调用 sleep , 线程 A 就会进入休眠状态 , 把 A 从就绪队列中取出放到阻塞队列中.


相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...