当前位置: 首页 > article >正文

Thread类及常见方法

目录

一、Thread常见构造方法

二、Thread常见属性

三、Thread常见方法

start()

获取当前线程

中断线程

join()


一、Thread常见构造方法

Thread类是JVM用来管理线程的一个类,每个线程都有唯一一个Thread对象与之对应,JVM会将这些对象组织起来,线程调度,线程管理。

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

二、Thread常见属性

属性获取方法
IDgetId()
名称getName()
状态getState()
优先级getPriority()
是否有后台线程isDaemon()
是否存活isAlive()
是否被中断isInterrupted()

getId(): ID是线程的唯一标识,不同的线程不重复

class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println("Hello world!");
    }
}
public class ThreadDemo {
    public static void main(String[] args) {
        Thread t = new MyThread();
        System.out.println(t.getId());

    }
}

getName: 名称是我们构造方法设置的名称,如果没有设置,那就是默认名。

public static void main(String[] args) {
        Thread t = new MyThread();
        System.out.println(t.getName());
    }

因为我们没有命名,所以使用的是默认名。
getState(): 指的是当前线程所处的状态 ( java当中的线程状态比操作系统中的状态更丰富,分的更细 ).

public static void main(String[] args) {
        Thread t = new MyThread();
        System.out.println(t.getState());
    }

这里NEW状态 (指的是线程对象已创建,但操作系统还没有为其分配PCB) 是什么大家先不用管,后面我们会详细介绍,只需要知道getState()方法是用来查看线程状态的。

getPriority: 我们可以获取当前线程的优先级,但没有太大的用,实际还得取决于操作系统内核的具体调度。

public static void main(String[] args) {
        Thread t = new MyThread();
        System.out.println(t.getPriority());
    }

isDaemon(): 是否为守护线程(也叫后台线程), 简单的理解一下,我们手动创建的线程都是前台线程,JVM自带的线程都是后台线程,我们也可以通过setDaemon()方法将前台线程设置为后台线程。

public static void main(String[] args) {
        Thread t = new MyThread();
        System.out.println(t.isDaemon());
    }

isAlive(): 线程的run方法是否执行结束。

public static void main(String[] args) {
        Thread t = new MyThread();
        System.out.println(t.isAlive());
        t.start();
        System.out.println(t.isAlive());
    }

三、Thread常见方法

start()

start() 启动一个线程。

只有当start(),操作系统内核才会创建一个真真正正的线程PCB,然后去调用run()方法。

获取当前线程

方法说明
sleep(long millis)休眠当前线程millis毫秒

由于线程调度是不可控的,我们sleep()方法的实际休眠是大于等于设置的时间的。我们的sleep方法也是Thread下的静态方法,直接类名调用即可。
需要注意的是我们在那个线程下面调用该方法,那个线程休眠。

使用sleep时会有一个中断异常(非受查异常),需要我们手动抛出

public static void main(String[] args) throws InterruptedException {
        System.out.println(System.currentTimeMillis());
        Thread.sleep(1000);
        System.out.println(System.currentTimeMillis());
    }

中断线程

线程中断: 我们这里的中断,并不是线程立即就结束了,而是通知该线程,你应该结束了,但实际是否结束,取决于线程里具体的代码

1.使用标志位来控制线程是否结束

public class ThreadDemo {
    private static boolean flg = true;

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

我们这个代码之所以能够起到修改flg就使线程结束,完全取决于线程内部的代码书写,我们只能起到一个通知作用,至于是否结束,还是取决于线程内部,即使我们sleep正在休眠,我们的标志位也可以唤醒sleep。

2. 调用 interrupt() 方法来通知

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

在唤醒sleep之后,我们的线程还在一直执行

interrupt()方法会做两件事:
1.把线程内部的标志位设置为true
2.如果线程正在sleep,会触发异常,将sleep唤醒。
sleep唤醒的同时,会清空标志位,将刚才设置的标志位在设置为false(这就导致,我们的循环会继续执行).
如果我们想去中断,我们可以在异常里加一个break。当我们sleep被唤醒时,结束run()方法。

这里再一次证明了,这里的中断只是通知线程,至于是否执行还得看线程内部的代码。

join()

join(): 等待一个线程
因为我们线程是随即调度的过程,线程的执行顺便我们无法把控,但在一些场景下我们需要有明确的线程程序顺序,等待线程,就是可以控制两个线程的结束顺序。

方法说明
join()等待线程结束
join(long millis)等待线程结束,最多等millis毫秒
public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            for (int i = 0; i < 3; i++) {
                System.out.println("My Thread!");
            }
        });
        t.start();
        t.join();
        System.out.println("Main!");
    }

如果去掉join()方法后,主线程与Thread线程抢占式执行!


http://www.kler.cn/a/393862.html

相关文章:

  • SpringCloud学习笔记
  • C++初阶:类和对象(上)
  • 【数据结构】交换排序——冒泡排序 和 快速排序
  • Springboot 日志处理(非常详细)
  • NoSQL数据库与关系型数据库的主要区别
  • 使用@react-three/fiber,@mkkellogg/gaussian-splats-3d加载.splat,.ply,.ksplat文件
  • 【Qt】在 Qt Creator 中使用图片资源方法(含素材网站推荐)
  • 实现API接口的自动化
  • PostgreSQL 开启密码验证插件
  • Spring-Webflux + Reactor + Netty 初体验
  • LeetCode【0017】电话号码的字母组合
  • Docker 基础命令介绍和常见报错解决
  • scala 迭代更新
  • Spring框架之适配器模式 (Adapter Pattern)
  • 江苏博才众创科技产业园集团拟投资10亿元在泰兴打造汽车零部件产业园
  • c#程序结构
  • 探索 HTTP 请求方法:GET、POST、PUT、DELETE 等的用法详解
  • 低代码、配置式web组态软件
  • Nop平台的定位及发展规划
  • 如何通过AB测试找到最适合的Yandex广告内容
  • 【IC每日一题:IC验证面试_UVM-1】
  • 渐进式JavaScript框架Vue 3 入门
  • 【Linux】内核参数修改
  • 洞察鸿蒙生态,把握开发新机遇
  • kafka生产经验——消费者事务
  • 使用 WebWorker 和 Rust WebAssembly 构建的生命游戏