线程的多种创建方式和使用

ops/2025/2/20 9:15:19/

一、线程的多种创建方式

在 Java 中,创建线程有多种方式,每种方式都有其特定的应用场景。以下是 Java 中常用的几种创建线程的方式,以及它们的具体实现:

1、通过继承 Thread 类创建线程

Java 中的 Thread 类提供了一个可执行的线程对象。通过继承 Thread 类并重写其 run() 方法来定义线程的执行体。

示例代码1:
java">class MyThread extends Thread {@Overridepublic void run() {// 线程要执行的代码System.out.println("Thread is running");}
}public class ThreadExample {public static void main(String[] args) {MyThread thread = new MyThread(); // 创建线程对象thread.start(); // 启动线程}
}
示例代码2:使用匿名内部类
java">public class AnonymousThreadExample {public static void main(String[] args) {// 创建线程并通过匿名内部类继承 Thread 类Thread thread = new Thread() {@Overridepublic void run() {// 线程要执行的代码System.out.println("Thread is running using Anonymous Thread");}};thread.start();  // 启动线程}
}
说明:
  • 优点:简单直接,适用于简单的线程创建。
  • 缺点:Java 中类只能继承一个类,因此如果已经继承了其他类,不能再继承 Thread 类。

2、通过实现 Runnable 接口创建线程

实现 Runnable 接口是一种更加灵活的方式,它可以避免 Java 单继承的限制。通过实现 Runnable 接口的 run() 方法来定义线程的执行体,再通过 Thread 类来启动该线程。

示例代码:
java">class MyRunnable implements Runnable {@Overridepublic void run() {// 线程要执行的代码System.out.println("Thread is running");}
}public class RunnableExample {public static void main(String[] args) {MyRunnable myRunnable = new MyRunnable(); // 创建 Runnable 实现类对象Thread thread = new Thread(myRunnable); // 将 Runnable 实现类传递给 Threadthread.start(); // 启动线程}
}
说明:
  • 优点:比继承 Thread 更灵活,可以同时继承其他类。适用于多线程共享同一资源的情况。
  • 缺点:需要通过 Thread 对象来启动线程,不能直接调用 start() 方法。

3、通过实现 Callable 接口创建线程(可返回值)

Callable 接口与 Runnable 类似,但它允许任务执行时返回结果,可以处理异常。通常与 ExecutorService 配合使用,能够提交任务并获得执行结果。

示例代码:
java">import java.util.concurrent.*;class MyCallable implements Callable<String> {@Overridepublic String call() throws Exception {// 线程要执行的代码return "Thread is running and returning result";}
}public class CallableExample {public static void main(String[] args) throws ExecutionException, InterruptedException {MyCallable myCallable = new MyCallable();ExecutorService executorService = Executors.newCachedThreadPool(); // 创建线程池Future<String> future = executorService.submit(myCallable); // 提交任务String result = future.get(); // 获取任务的执行结果System.out.println(result); // 输出结果executorService.shutdown(); // 关闭线程池}
}
说明:
  • 优点:能够返回任务执行结果,适用于需要计算并返回结果的场景。
  • 缺点:需要使用 ExecutorService 来执行任务,相比 Runnable 略显复杂。

4、通过 ExecutorService 创建线程池

线程池是一种管理线程的方式,通过 ExecutorService 可以创建线程池并提交任务,线程池会自动管理线程的创建、销毁和复用。通过线程池可以有效地管理多线程任务,避免频繁的线程创建销毁操作。

示例代码:
java">import java.util.concurrent.*;class MyTask implements Runnable {@Overridepublic void run() {System.out.println("Thread is running from ExecutorService");}
}public class ExecutorServiceExample {public static void main(String[] args) {ExecutorService executorService = Executors.newFixedThreadPool(3); // 创建固定大小的线程池for (int i = 0; i < 5; i++) {executorService.submit(new MyTask()); // 提交任务给线程池}executorService.shutdown(); // 关闭线程池}
}
说明:
  • 优点:可以管理大量线程,自动复用线程,提高性能。适用于高并发的场景。
  • 缺点:需要额外的线程池管理,使用稍微复杂。

5、通过 ForkJoinPool 创建线程(适用于分治任务)

ForkJoinPool 是一种专门用于处理大规模并行任务的线程池,特别适合分治型任务的执行。它通过将任务分割为多个子任务并行执行来提高性能。

示例代码:
java">import java.util.concurrent.*;class MyForkJoinTask extends RecursiveTask<Integer> {@Overrideprotected Integer compute() {// 线程要执行的代码return 1; // 示例返回值}
}public class ForkJoinPoolExample {public static void main(String[] args) {ForkJoinPool forkJoinPool = new ForkJoinPool(); // 创建 ForkJoinPoolMyForkJoinTask task = new MyForkJoinTask();ForkJoinTask<Integer> result = forkJoinPool.submit(task); // 提交任务System.out.println("Result: " + result.join()); // 获取结果forkJoinPool.shutdown(); // 关闭线程池}
}
说明:
  • 优点:适合计算密集型任务和分治型任务,能够有效处理大量子任务。
  • 缺点:相对于其他线程池,使用场景更为特殊。

6、通过 Lambda 表达式创建线程(简化代码)

Java 8 引入了 Lambda 表达式,可以简化线程的创建过程。通常与 Runnable 接口配合使用,能够在一行代码中定义线程的执行内容。

示例代码:
java">public class LambdaThreadExample {public static void main(String[] args) {// 使用 Lambda 表达式创建线程Thread thread = new Thread(() -> {System.out.println("Thread is running using Lambda");});thread.start(); // 启动线程}
}
说明:
  • 优点:代码简洁,减少了冗长的类定义,适用于快速创建简单线程。
  • 缺点:仅适用于 Runnable 接口场景,对于其他接口无法使用。

7、总结

Java 提供了多种方式来创建线程,每种方式都有其特定的优势和适用场景:

  1. 继承 Thread 类:适合简单的线程创建,但不能继承其他类。
  2. 实现 Runnable 接口:适合多线程共享资源的情况,比继承 Thread 更灵活。
  3. 实现 Callable 接口:适合需要返回结果的线程任务,通常与 ExecutorService 配合使用。
  4. 使用 ExecutorService:适合管理大量线程,自动复用线程,提高系统性能。
  5. 使用 ForkJoinPool:适合大规模并行计算和分治型任务。
  6. 使用 Lambda 表达式:适合快速创建简单线程,代码简洁。

选择哪种方式,取决于具体应用场景和任务需求。在实际开发中,通常推荐使用 ExecutorServiceForkJoinPool 来管理线程,以提高代码的可维护性和性能。

二、Thread类最常用个方法

1. start()

功能:启动一个新线程,使其进入就绪状态,等待操作系统调度执行。

  • 作用:启动线程后,JVM 会自动调用 run() 方法,并在新的线程中执行。
  • 注意:线程一旦启动后,不能再次启动。如果调用 start() 方法多次,会抛出 IllegalThreadStateException 异常。
Thread thread = new Thread(() -> System.out.println("Thread is running"));
thread.start();  // 启动线程

2. run()

功能:线程的执行体方法,定义线程启动后要执行的代码。

  • 作用:当调用 start() 启动线程时,JVM 会调用 run() 方法。通常情况下,run() 方法会被覆盖,定义线程的具体执行逻辑。
  • 注意:直接调用 run() 方法只是将 run() 方法作为普通方法调用,并不会启动新的线程,仍然是在主线程中执行。
java">@Override
public void run() {System.out.println("Thread is running");
}

3. sleep(long millis)

功能:让当前线程暂停指定时间(以毫秒为单位),进入 休眠状态,不会占用 CPU 资源。

  • 作用:使当前线程暂时进入休眠状态,休眠结束后,线程会回到就绪状态,等待操作系统调度。
  • 注意sleep() 方法是静态的,作用于调用它的当前线程,且可以抛出 InterruptedException 异常。
java">try {Thread.sleep(1000);  // 当前线程暂停 1000 毫秒(1秒)
} catch (InterruptedException e) {e.printStackTrace();
}

4. join()

功能:使当前线程等待目标线程完成后再继续执行,常用于 线程同步

  • 作用join() 方法会使当前线程等待调用它的线程(即目标线程)执行完毕后再继续执行。
  • 注意:可以指定等待时间,等待超时后 join() 方法会返回。
java">// 创建子线程对象
Thread thread = new Thread(() -> System.out.println("Thread is running"));
// 执行子线程
thread.start();
try {thread.join();  // 当前线程(即:主线程)等待子线程执行完
} catch (InterruptedException e) {e.printStackTrace();
}

5. interrupt()

功能:中断一个线程,设置线程的中断标志为 true,通知线程终止。

  • 作用:如果线程正在执行 sleep()wait()join() 等阻塞操作,interrupt() 会使这些操作抛出 InterruptedException,从而让线程终止或者退出阻塞。
  • 注意interrupt() 只是设置线程的中断标志,不会立即停止线程的执行。线程需要在合适的地方自行判断 Thread.interrupted() 或捕获 InterruptedException 来响应中断。
java">Thread thread = new Thread(() -> {try {Thread.sleep(5000);} catch (InterruptedException e) {System.out.println("Thread was interrupted");}
});
thread.start();
thread.interrupt();  // 中断线程

6. isAlive()

功能:判断线程是否已经启动并正在执行。

  • 作用:返回线程是否处于活动状态。如果线程处于 新建状态已死亡状态,返回 false;否则返回 true
java">Thread thread = new Thread(() -> System.out.println("Thread is running"));
thread.start();
System.out.println(thread.isAlive());  // true

7. getName()

功能:获取线程的名称。

  • 作用:返回当前线程的名字,通常是由 JVM 自动分配的,如 Thread-0Thread-1 等,也可以手动通过 setName() 方法来设置。
java">Thread thread = new Thread(() -> System.out.println(Thread.currentThread().getName()));
thread.start();  // 输出:Thread-0

8. setName(String name)

功能:设置线程的名称。

  • 作用:给当前线程指定一个名称。为线程设置名称有助于在调试和日志中跟踪线程。
java">Thread thread = new Thread(() -> System.out.println(Thread.currentThread().getName()));
thread.setName("CustomThread");
thread.start();  // 输出:CustomThread

9. getId()

功能:获取线程的唯一标识符。

  • 作用:返回当前线程的唯一 ID,通常用于调试和标识线程。
java">Thread thread = new Thread(() -> System.out.println(Thread.currentThread().getId()));
thread.start();  // 输出线程的 ID,例如:1

10. setPriority(int priority)

功能:设置线程的优先级,影响线程获取 CPU 时间片的频率。

  • 作用setPriority() 方法允许你设置线程的优先级(从 1 到 10,默认值为 5)。高优先级线程通常会更早地获得 CPU 时间片,但这也依赖于操作系统的线程调度策略。
java">Thread thread = new Thread(() -> System.out.println("Thread is running"));
thread.setPriority(Thread.MAX_PRIORITY);  // 设置为最高优先级
thread.start();

11. yield()

功能:使当前线程放弃 CPU 时间片,暂时让出 CPU 资源,允许其他线程执行。

  • 作用yield() 是一个静态方法,当前线程会让出 CPU 使用权,但是不会完全让出控制权,仍然可以继续执行。具体行为依赖于操作系统的线程调度策略。
java">Thread.yield();  // 当前线程暂停,让出 CPU 资源

12. currentThread()

功能:获取当前正在执行的线程对象。

  • 作用:返回代表当前正在执行线程的 Thread 对象。常用于获取当前线程的状态、名称等信息。
java">Thread current = Thread.currentThread();
System.out.println(current.getName());  // 输出当前线程的名称

三. 线程的生命周期


http://www.ppmy.cn/ops/159655.html

相关文章

JavaScript与AJAX:让网页动起来的魔法与秘密

前言:当网页开始学会"呼吸" 还记得20年前的互联网吗?每次点击链接都要经历漫长的白屏等待,网页像笨拙的机器人一样机械地刷新。直到有一天,JavaScript遇见AJAX,网页突然被注入了灵魂。就像给木偶系上了提线,原本死板的页面开始学会呼吸,能悄悄和服务器说悄悄…

OlympicArena 论文简介

近年来&#xff0c;大型语言模型&#xff08;LLMs&#xff09;和大型多模态模型&#xff08;LMMs&#xff09;的飞速发展&#xff0c;让AI逐渐展现出接近人类水平的认知推理能力。然而&#xff0c;如何科学评估AI在复杂问题解决中的真实水平&#xff0c;一直是学术界和产业界的…

【Java进阶篇】——第11篇:Java 8 新特性及使用

第11篇&#xff1a;Java 8 新特性及使用 Java 8 是一次里程碑式的更新&#xff0c;引入了多项革新特性&#xff0c;极大地提升了开发效率和代码表现力。本文将从 Lambda表达式、Stream API、时间日期API、Optional类 等核心特性出发&#xff0c;结合实战场景和最佳实践&#x…

多目标蜻蜓算法-MODA-可用于(云计算资源分配/交通信号控制/网络路由优化)

多目标蜻蜓算法&#xff08;Multi-Objective Dragonfly Algorithm&#xff0c;MODA&#xff09;是一种基于群体智能的优化算法&#xff0c;主要用于解决多目标优化问题。以下是对其的详细介绍&#xff1a; 具体完整算法请跳转&#xff1a;多目标蜻蜓算法-MODA-可用于&#xff0…

【系列教程】Python第四课:条件判断 | 让程序学会思考的秘密

&#x1f3af; 本节目标 掌握if-elif-else逻辑结构理解比较运算符的用法学会用布尔值控制程序流程完成智能登录验证系统开发 1️⃣ if语句基础&#xff08;程序决策树) &#x1f680; 基础语法 # 简单判断示例 age int(input("请输入你的年龄&#xff1a;"))if …

K8s:kubernetes.io~csi 目录介绍

目录标题 **1. 进入 CSI 相关目录****2. PVC 相关目录操作****3. 挂载点相关操作****4. CSI PVC 的使用流程****5. 总结** 在 Kubernetes&#xff08;K8s&#xff09;中&#xff0c;容器存储接口&#xff08;CSI&#xff09; 是一种标准&#xff0c;用于将存储系统暴露给 K8s 中…

无人设备遥控器之视频回传篇

无人设备遥控器的视频回传是指将无人设备&#xff08;如无人机&#xff09;采集到的视频信号传输回遥控器或其他接收设备的过程。这一过程在诸多应急情境中显得尤为重要&#xff0c;它能为指挥中心的决策者、调度系统以及AI分析等提供实时画面。 一、主流回传方式 目前&#x…

Django创建一个非前后端分离平台

1.pub_blog前端创立 1.blog/pub路由 注意两个路由的区别 2.完善页面 用表单实现 3.加载wangeditor的几个文件 4.配置样式 5.配置js代码&#xff0c;单独放在js文件夹中&#xff0c;js文件夹pub_blog onload事件&#xff0c;加载完成后会再加载 5.提交按钮