【JavaEE】多线程之Thread类(下)

发布于:2025-08-09 ⋅ 阅读:(12) ⋅ 点赞:(0)

前面link我们了解了Thread类中的常用属性,本节我们来介绍Thread相关的方法以及几种基本的线程操作

1. 常用方法

1.1 构造方法

方法名 说明
Thread() 创建线程对象(必须重写Thread类的run方法)
Thread(Runnable target) 使用Runnable对象创建线程对象(不需要重写run方法)
Thread(String name) 创建线程对象并命名
Thread(Runnable target, String name) 使用Runnable对象创建线程对象并命名
Thread(ThreadGroup group, Runnable target) 线程可以被用来分组管理,分好的组即为线程组

几点说明:

  1. Run方法相当于线程的入口,里面封装的是这个线程实际执行的任务
  2. Thread这个父类中本身存在一个run方法,因此如果通过自行创建MyThread类创建线程的话,就要重写这个run方法以实现所需功能
  3. Runnable这个类下文创建线程时我们还会提到,暂且按下不表
  4. 线程的命名只是为了方便程序员调试、调用代码
  5. 线程组:把多个线程放在一个组里,统一针对这个线程组里所有线程进行一些属性设置

1.2 sleep()

sleep()是一个Thread类中的静态方法,作用是让当前线程暂时放弃CPU(当前线程休眠),有一个参数,单位是毫秒,代表休眠的时长

必须捕获或声明抛出InterruptedException异常

当线程在休眠时被其他线程中断(调用interrupt()),会抛出该异常,且线程的中断状态会被清除

sleep(0)是一种特殊的写法,意味着让当前线程立即放弃CPU资源,等待操作系统重新调度

由于线程的调度是不可控的,这个方法之恶能保证实际休眠时间大于等于参数设置的休眠时间

1.3 start()

start()方法用来启动一个新线程,并由 JVM 调用该线程的run()方法执行具体任务,也就是说,创建好线程对象之后,需要调用这个方法才会给这个线程分配资源,让线程真正地运行起来

start方法和run方法的区别在于,start是在系统中真实地创建一个新的线程,由新的线程执行run方法,而run方法可以看作一个普通的方法调用

1.4 join()

有三个重载的方法

方法名 说明
public void join() 等待线程结束
public void join(long millis,) 等待线程结束,最多等待millis毫秒
public void join(long millis, int nanos) 和前一个方法同理,可以提高精度

join方法能够要求多个线程之间结束的先后顺序——也就是让当前线程停下来,等待另一个线程执行完毕后再继续自己的工作
举个例子:

public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            for (int i = 0; i < 3; i++) {
                System.out.println("thread running");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println("something wrong with t");
                }
            }
            System.out.println("t 线程结束");
        });
        t.start();
        //main 线程阻塞等待 t 线程
        t.join();

        System.out.println("main 线程结束");
    }

这段代码中,t.join(); 语句的作用就是让main线程阻塞等待t线程

在A线程中B.join();,等待关系为让A线程等待B线程先结束

join带参数的版本里指定了“超时时间”,也就是等待的最大时间,超过这个时间的线程就会停止阻塞状态继续执行(类似于sleep方法)

1.5 获取对应线程的引用

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

哪个线程调用这个方法,就返回哪个线程的引用(类似于this)

2. 线程基本操作

2.1 创建线程

创建线程的写法可以大致分为五种:

  1. 继承Thread类,重写run方法(将要执行的内容直接通过thread对象进行描述)
import static java.lang.Thread.sleep;
class MyThread extends Thread{

    public void run(){
        while(true){
            System.out.println("Hello thread!");
        }
    }
}
  1. 实现Runnable,重写run方法(将要执行的内同写入runnable对象, 进而调用执行)
class MyRunnable implements Runnable{
    public void run(){
        while(true){
            System.out.println("Hello thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

//主函数
Runnable runnable = new MyRunnable();
Thread t = new Thread(runnable);

这种方法的耦合度更低,任务和线程的概念是分开的

  1. 使用匿名内部类(本质上还是1)
public static void main(String[] args) {
        //创建一个匿名内部类
        Thread thread = new Thread(){
            public void run(){
                while(true){
                    System.out.println("Hello mythread!");
                    }
                }
            }
        };
    }

这种方法好处在于,对于使用次数较少的类来说,相比单独定义一个类,定义匿名内部类会更简单高效

  1. 使用Runnable实现匿名内部类
    和上一种方式没有太多区别,这里不过多赘述~
  2. 使用lambda表达式(最简单的写法)
Thread t = new Thread(() ->{
            while(true){
                System.out.println("Hello mythread!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

lambda表达式本质上是一个匿名函数,最主要的用途是最为回调函数

2.2 启动线程

上文提过的start()方法,是Java标准库/JVM提供的代码,本质上是调用操作系统的API

每个Thread对象都是只能start一次的,也就是每次像创建一个新的进程,就要创建一个新的Thread对象

2.3 终止线程

即为结束线程,Java中只要让线程的入口方法(run方法)执行完毕,线程就随之结束了

2.4 等待线程

也就是调用join()方法,实现一个线程等待另一个线程先结束

2.5 线程休眠

调用sleep方法让线程休眠若干时间


嘿嘿,多线程基础知识篇结束^ - ^ 接下来将是多线程最关键的要点——线程安全~


网站公告

今日签到

点亮在社区的每一天
去签到