Thread 常用API(详细解析)

本文介绍了Java中多线程的关键方法,包括start()用于启动线程执行run()里的代码,run()定义线程任务,join()使主线程等待子线程结束,sleep()让线程休眠,interrupt()中断线程,yield()让当前线程放弃CPU时间片,以及currentThread()返回当前线程对象。
摘要由CSDN通过智能技术生成

start()

启动线程,运行 run 方法中的代码
注意

  • start 方法只是让 线程进入了 就绪,而不是马上运行,需要等待CPU的时间片
  • 一个线程只能调用一次 start,否则会出现 IllegalThreadStateException

代码实例

        Thread t1=new Thread(() -> {
            System.out.println("线程1 运行");
        });
        Thread t2=new Thread(() -> {
            System.out.println("线程2 运行");
        });

        t1.start();
        t2.start();

上面代码的的运行结果可能是
在这里插入图片描述
虽然 线程1 比 线程2 更早进入就绪态,但是 线程2 比 线程1 更早获取到CPU时间片,因此更早执行

run()

在该方法中定义线程要完成的任务

以下是Runnable接口的源码

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

可以看到加了 @FunctionalInterface ,是函数式接口,并且只有一个run方法

我们看Thread源码,发现Thread的run方法就是来源于 Runnable 接口

public class Thread implements Runnable

我们可以直接重写 Thread 中的run方法,比如

		Thread t3 = new Thread(){
            @Override
            public void run() {
                System.out.println("线程3 运行");
            }
        };
        t3.start();

也可以继承 Thread 类后再重写

public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("MyThread...run...");
    }    
    public static void main(String[] args) {
        // 创建MyThread对象
        MyThread t1 = new MyThread() ;
        MyThread t2 = new MyThread() ; 
    }
    
}

观察Thread源码,发现存在Runnable属性

    /* What will be run. */
    private Runnable target;

因此,也可以在构造 Thread 对象时传递 Runnable 参数,则线程启动后会调用 Runnable 中的 run 方法

代码实例

        Thread t1=new Thread(() -> {
            System.out.println("线程1 运行");
        });
        Thread t2=new Thread(() -> {
            System.out.println("线程2 运行");
        });

        t1.start();
        t2.start();

在上面的代码中,调用的 Thread 构造方法,如下

    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }

我们使用Lambda表达式实现了Runnable接口的run方法

可以用一句话概括,如果 Thead 类上的Runnable属性不为null,则执行该Runnable属性的run方法,否则执行Thread自己的run方法

join() 和 join(long n)

join() – 等待线程运行结束
join(long n) – 等待线程运行结束,最多等待 n 毫秒

        Thread t3 = new Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        t3.start();

        t3.join();

        System.out.println("main 继续执行");

执行上面的代码会发现,无论如何都会等待至少10秒才会输出 “main 继续执行”

sleep(long n)

sleep是Thread的静态方法

作用是:让当前执行的线程休眠 n 毫秒,休眠时让出 cpu 的时间片给其它线程

上面的代码实例就已经使用到 sleep 方法

哪个线程调用了 Thread.sleep(10000) ,哪个线程睡眠

比如在上面的代码实例中,线程3 会睡眠 10 秒,而 主线程 并不会睡眠

另外

  • 睡眠结束后的线程未必会立刻得到执行
  • 其它线程可以使用 interrupt 方法打断正在睡眠的线程,这时 sleep 方法会抛出 InterruptedException
  • 建议用 TimeUnit 的 sleep 代替 Thread 的 sleep来获得更好的可读性 (TimeUnit 的 sleep方法与 Thread的sleep方法相同)

interrupt()

interrupt 打断线程

无论线程处在阻塞(sleep、wait、join)还是运行状态,都可以被打断

如果被打断线程正在 sleep、wait、join 会导致被打断的线程抛出 InterruptedException,并清除 打断标记 ;如果打断的正在运行的线程,则会设置 打断标记 ;

interrupt 是非静态方法,需要打断哪个线程,就调用那个线程的 interrupt方法

代码实例

    private static void test1() throws InterruptedException {
        Thread t1 = new Thread(()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t1");
        t1.start();
        Thread.sleep(500);
        t1.interrupt();
    }

yield()

sleep 能使线程让出 CPU时间片

而 yield方法 同样 能使线程让出CPU时间片

但是 调用 yield 方法时,线程不一定会马上让出CPU,这取决于操作系统的任务调度器

而且 sleep 方法是让线程从 Running 进入 Timed Waiting 状态(阻塞),yield是让当前线程从 Running 进入 Runnable 就绪状态

yield方法也是个静态方法

currentThread()

public static native Thread currentThread();

可以看到currentThread也是个静态方法,并且返回值是Thread

用法 – 在哪个线程中调用 Thread.currentThread ,就会返回当前线程的 Thread 对象,有点类似 this 关键字

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值