首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Java EE初阶启程记03---Thread类及常见方法

Java EE初阶启程记03---Thread类及常见方法

作者头像
寻星探路
发布2025-12-17 19:16:35
发布2025-12-17 19:16:35
530
举报
文章被收录于专栏:CSDN博客CSDN博客

Thread类是JVM用来管理线程的一个类,换句话说,每个线程都有一个唯一的Thread对象与之关联。

用我们上面的例子来看,每个执行流,也需要有⼀个对象来描述,类似下图所示,而Thread类的对象就是用来描述一个线程执行流的,JVM会将这些Thread对象组织起来,用于线程调度,线程管理。

1、Thread的常见构造方法

代码语言:javascript
复制
 Thread t1 = new Thread();
 Thread t2 = new Thread(new MyRunnable());
 Thread t3 = new Thread("这是我的名字");
 Thread t4 = new Thread(new MyRunnable(), "这是我的名字");

2、Thread的几个常见属性

ID是线程的唯一标识,不同线程不会重复

名称是各种调试工具用到

状态表示线程当前所处的⼀个情况,下面我们会进一步说明

优先级高的线程理论上来说更容易被调度到

关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行。

是否存活,即简单的理解,为run方法是否运行结束了

线程的中断问题,下面我们进一步说明

代码语言:javascript
复制
public class ThreadDemo {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + ": 我还活着");
                    Thread.sleep(1 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + ": 我即将死去");
        });

        System.out.println(Thread.currentThread().getName() + ": ID: " + thread.getId());
        System.out.println(Thread.currentThread().getName() + ": 名称: " + thread.getName());
        System.out.println(Thread.currentThread().getName() + ": 状态: " + thread.getState());
        System.out.println(Thread.currentThread().getName() + ": 优先级: " + thread.getPriority());
        System.out.println(Thread.currentThread().getName() + ": 后台线程: " + thread.isDaemon());
        System.out.println(Thread.currentThread().getName() + ": 活着: " + thread.isAlive());
        System.out.println(Thread.currentThread().getName() + ": 被中断: " + thread.isInterrupted());

        thread.start();
        while (thread.isAlive()) {}
        System.out.println(Thread.currentThread().getName() + ": 状态: " + thread.getState());
    }
 }

3、启动一个线程---start()

之前我们已经看到了如何通过覆写run方法创建⼀个线程对象,但线程对象被创建出来并不意味着线程就开始运行了。

覆写run方法是提供给线程要做的事情的指令清单

线程对象可以认为是把李四、王五叫过来了

而调用start()方法,就是喊⼀声:”行动起来!“,线程才真正独立去执行了。

调用start方法,才真的在操作系统的底层创建出一个线程

4、中断一个线程

李四⼀旦进到工作状态,他就会按照行动指南上的步骤去进行工作,不完成是不会结束的。但有时我们需要增加⼀些机制,例如老板突然来电话了,说转账的对方是个骗子,需要赶紧停止转账,那张三该如何通知李四停止呢?这就涉及到我们的停止线程的方式了。

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

1)通过共享的标记来进行沟通

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

示例---1:使用自定义的变量来作为标志位

需要给标志位上加volatile关键字(这个关键字的功能后面介绍)

代码语言:javascript
复制
public class ThreadDemo {
    private static class MyRunnable implements Runnable {
        public volatile boolean isQuit = false;
        @Override
        public void run() {
            while (!isQuit) {
                System.out.println(Thread.currentThread().getName()
                        + ": 别管我,我忙着转账呢!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()+ ": 啊!险些误了⼤事");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "李四");
        System.out.println(Thread.currentThread().getName() + ": 让李四开始转账。");
        thread.start();
        Thread.sleep(10 * 1000);
        System.out.println(Thread.currentThread().getName()+ ": ⽼板来电话了,得赶紧通知李四对⽅是个骗⼦!");
        target.isQuit = true;
    }
}

示例---2:使用Thread.interrupted()或者Thread.currentThread().isInterrupted()代替自定义标志位

Thread内部包含了一个boolean类型的变量作为线程是否被中断的标记

使用thread对象的 interrupted() 方法通知线程结束

代码语言:javascript
复制
public class ThreadDemo {
    private static class MyRunnable implements Runnable {
        @Override
        public void run() {
            // 两种⽅法均可以
 
            while (!Thread.interrupted()) {
            //while (!Thread.currentThread().isInterrupted()) {
                System.out.println(Thread.currentThread().getName()+ ": 别管我,我忙着转账呢!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println(Thread.currentThread().getName()+ ": 有内⻤,终⽌交易!");
                    // 注意此处的 break 
                    break;
                }
            }
            System.out.println(Thread.currentThread().getName()+ ": 啊!险些误了⼤事");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "李四");
        System.out.println(Thread.currentThread().getName()+ ": 让李四开始转账。");
        thread.start();
        Thread.sleep(10 * 1000);
        System.out.println(Thread.currentThread().getName()+ ": ⽼板来电话了,得赶紧通知李四对⽅是个骗⼦!");
        thread.interrupt();
    }
 }

thread收到通知的方式有两种:

1)如果线程因为调用wait/join/sleep等方法而阻塞挂起,则以InterruptedException异常的形式通 知,清除中断标志

当出现InterruptedException的时候,要不要结束线程取决于catch中代码的写法,可以选择忽 略这个异常,也可以跳出循环结束线程

2)否则,只是内部的一个中断标志被设置,thread可以通过 Thread.currentThread().isInterrupted()判断指定线程的中断标志被设置,不清除中断标志这种方式通知收到的更及时,即使线程正在sleep也可以马上收到。

5、等待一个线程---join()

有时,我们需要等待一个线程完成它的工作后,才能进行自己的下一步工作。例如,张三只有等李四转账成功,才决定是否存钱,这时我们需要⼀个方法明确等待线程的结束。

代码语言:javascript
复制
public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        Runnable target = () -> {
            for (int i = 0; i < 10; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + ": 我还在⼯作!");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
         }
         System.out.println(Thread.currentThread().getName() + ": 我结束了!");
};

         Thread thread1 = new Thread(target, "李四");
         Thread thread2 = new Thread(target, "王五");
         System.out.println("先让李四开始⼯作");
         thread1.start();
         thread1.join();
         System.out.println("李四⼯作结束了,让王五开始⼯作");
         thread2.start();
         thread2.join();
         System.out.println("王五⼯作结束了");
     }
}

大家可以试试如果把两个join注释掉,现象会是怎么样的呢?

6、获取当前线程引用

这个方法我们已经非常熟悉了

代码语言:javascript
复制
public class ThreadDemo {
    public static void main(String[] args) {
        Thread thread = Thread.currentThread();
        System.out.println(thread.getName());
    }
}

7、休眠当前线程

也是我们比较熟悉⼀组方法,有⼀点要记得,因为线程的调度是不可控的,所以,这个方法只能保证实际休眠时间是大于等于参数设置的休眠时间的

代码语言:javascript
复制
 public class ThreadDemo {
     public static void main(String[] args) throws InterruptedException {
         System.out.println(System.currentTimeMillis());
         Thread.sleep(3 * 1000);
         System.out.println(System.currentTimeMillis());
     }
 }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-12-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、Thread的常见构造方法
  • 2、Thread的几个常见属性
  • 3、启动一个线程---start()
  • 4、中断一个线程
  • 5、等待一个线程---join()
  • 6、获取当前线程引用
  • 7、休眠当前线程
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档