Thread 常用API(详细解析)

简介: 学习 Thread 的常用API,包括 start、run、join、sleep、interrupt、yield、currentThread 方法的概念、使用方法以及代码实例

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();

上面代码的的运行结果可能是

线程2 运行
线程1 运行

虽然 线程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 关键字

目录
相关文章
|
1月前
|
监控 前端开发 JavaScript
实战篇:商品API接口在跨平台销售中的有效运用与案例解析
随着电子商务的蓬勃发展,企业为了扩大市场覆盖面,经常需要在多个在线平台上展示和销售产品。然而,手工管理多个平台的库存、价格、商品描述等信息既耗时又容易出错。商品API接口在这一背景下显得尤为重要,它能够帮助企业在不同的销售平台之间实现商品信息的高效同步和管理。本文将通过具体的淘宝API接口使用案例,展示如何在跨平台销售中有效利用商品API接口,以及如何通过代码实现数据的统一管理。
|
2月前
|
tengine 网络协议 API
阿里云DNS常见问题之DNS中alidns的api调用失败如何解决
阿里云DNS(Domain Name System)服务是一个高可用和可扩展的云端DNS服务,用于将域名转换为IP地址,从而让用户能够通过域名访问云端资源。以下是一些关于阿里云DNS服务的常见问题合集:
|
2月前
|
API 数据库 C语言
【C/C++ 数据库 sqlite3】SQLite C语言API返回值深入解析
【C/C++ 数据库 sqlite3】SQLite C语言API返回值深入解析
171 0
|
2月前
|
存储 前端开发 算法
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析(一)
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析
49 0
|
2月前
|
存储 并行计算 Java
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析(二)
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析
68 0
|
9天前
|
SQL 关系型数据库 API
从API获取数据并将其插入到PostgreSQL数据库:步骤解析
使用Python处理从API获取的数据并插入到PostgreSQL数据库:安装`psycopg2`,建立数据库连接,确保DataFrame与表结构匹配,然后使用`to_sql`方法将数据插入到已存在的表中。注意数据准备、权限设置、性能优化和安全处理。
|
16天前
|
机器学习/深度学习 API TensorFlow
TensorFlow的高级API:tf.keras深度解析
【4月更文挑战第17天】本文深入解析了TensorFlow的高级API `tf.keras`,包括顺序模型和函数式API的模型构建,以及模型编译、训练、评估和预测的步骤。`tf.keras`结合了Keras的易用性和TensorFlow的性能,支持回调函数、模型保存与加载等高级特性,助力提升深度学习开发效率。
|
21天前
|
存储 Java 关系型数据库
解锁Java8的秘密武器:Stream API全面解析
解锁Java8的秘密武器:Stream API全面解析
54 0
解锁Java8的秘密武器:Stream API全面解析
|
24天前
|
JavaScript API UED
Vue3.0新特性解析与实战:Composition API、Teleport与Suspense
【4月更文挑战第6天】Vue3.0引入了颠覆性的Composition API,通过函数式方法提升代码可读性和复用性,例如`setup()`、`ref`等,便于逻辑模块化。实战中,自定义的`useUser`函数可在多个组件中共享用户信息逻辑。另外,Teleport允许组件渲染到DOM特定位置,解决模态框等场景的上下文问题。再者,Suspense提供异步组件加载的延迟渲染,使用fallback内容改善用户体验。这些新特性显著优化了开发和性能,适应现代Web需求。
21 0
|
2月前
|
存储 安全 Linux
【Linux 创建临时文件 API】编程中的瞬息之光:临时文件的艺术与智慧 tmpnam,tmpfile,mkstemp,mkdtemp等函数解析...
【Linux 创建临时文件 API】编程中的瞬息之光:临时文件的艺术与智慧 tmpnam,tmpfile,mkstemp,mkdtemp等函数解析...
24 0

推荐镜像

更多