当前位置: 首页 > news >正文

Java 创建线程的方式有哪几种

在 Java 中,创建线程的方式有四种,分别是:继承 Thread 类、实现 Runnable 接口、使用 CallableFuture、使用线程池。以下是详细的解释和通俗的举例:


1. 继承 Thread

通过继承 Thread 类并重写 run() 方法来创建线程。

步骤:

  1. 创建一个 Thread 类的子类,重写 run() 方法,定义线程执行的任务。
  2. 创建该子类的实例,并调用 start() 方法启动线程。

代码示例:

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();  // 启动线程}
}

解释:

  • MyThread 类继承了 Thread 类,重写了 run() 方法,run() 方法里是线程执行的任务。
  • 调用 start() 方法启动线程,start() 方法会调用 run() 方法,线程开始执行。

优点:

  • 代码简单,适合不需要线程共享资源的场景。

缺点:

  • 继承 Thread 类无法再继承其他类,因为 Java 不支持多重继承。

2. 实现 Runnable 接口

创建一个实现了 Runnable 接口的类,并实现其 run() 方法。然后将该实例作为参数传递给 Thread 对象来创建线程。

步骤:

  1. 创建一个实现了 Runnable 接口的类,并重写 run() 方法。
  2. 创建 Runnable 实例,将其传递给 Thread 构造方法。
  3. 调用 start() 启动线程。

代码示例:

class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("Runnable 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();  // 启动线程}
}

解释:

  • MyRunnable 类实现了 Runnable 接口,并重写了 run() 方法,定义线程执行的任务。
  • Thread 构造方法接收 Runnable 对象,调用 start() 启动线程。

优点:

  • 适用于多个线程共享同一个 Runnable 对象的场景。
  • 可以避免 Thread 类的单继承限制,Runnable 实现类可以继承其他类。

缺点:

  • 线程任务无法返回结果或抛出异常。

3. 使用 CallableFuture 接口

Callable 接口与 Runnable 接口类似,但它能够返回结果,并且可以抛出异常。通过 ExecutorService 来管理线程池,并提交 Callable 任务获取 Future 对象,以便在未来某个时刻获取任务的计算结果。

步骤:

  1. 创建实现 Callable 接口的类,重写 call() 方法,定义线程任务,并返回结果。
  2. 使用 ExecutorService 提交任务,返回一个 Future 对象,可以用来获取任务执行的结果。

代码示例:

import java.util.concurrent.*;class MyCallable implements Callable<Integer> {@Overridepublic Integer call() throws Exception {System.out.println("Callable thread is running...");return 42;  // 返回结果}
}public class CallableExample {public static void main(String[] args) throws Exception {ExecutorService executor = Executors.newSingleThreadExecutor();  // 创建线程池MyCallable myCallable = new MyCallable();Future<Integer> future = executor.submit(myCallable);  // 提交任务// 获取任务的执行结果Integer result = future.get();System.out.println("Result: " + result);executor.shutdown();  // 关闭线程池}
}

解释:

  • MyCallable 实现了 Callable 接口,重写了 call() 方法,返回结果 42
  • 使用 ExecutorService 来创建线程池并提交 Callable 任务。
  • future.get() 会阻塞并返回任务执行的结果。

优点:

  • 适用于需要任务返回结果或需要处理异常的场景。
  • ExecutorService 提供了线程池管理,线程复用,提高了效率。

缺点:

  • 使用 Future.get() 时会阻塞,直到任务完成并返回结果。

4. 使用线程池 (ExecutorService)

通过使用 ExecutorService 来创建和管理线程池,并提交任务。线程池允许线程复用,避免了频繁创建和销毁线程的开销。

步骤:

  1. 使用 ExecutorService 创建线程池,通常使用 Executors 类来创建。
  2. 提交任务到线程池执行,可以提交 RunnableCallable 任务。

代码示例:

import java.util.concurrent.*;class MyRunnableTask implements Runnable {@Overridepublic void run() {System.out.println("Task is running in thread pool...");}
}public class ExecutorServiceExample {public static void main(String[] args) {ExecutorService executor = Executors.newFixedThreadPool(2);  // 创建线程池,最多2个线程executor.submit(new MyRunnableTask());  // 提交任务executor.submit(new MyRunnableTask());  // 提交另一个任务executor.shutdown();  // 关闭线程池}
}

解释:

  • 使用 Executors.newFixedThreadPool(2) 创建了一个最多包含两个线程的线程池。
  • 提交多个 Runnable 任务到线程池,线程池负责线程的创建和管理。
  • shutdown() 方法用于关闭线程池。

优点:

  • 可以复用线程,避免了每次创建新线程的开销。
  • 线程池可以根据系统资源动态调整线程数量,适用于高并发场景。

缺点:

  • 需要管理线程池的生命周期,避免线程池资源泄漏。

总结

  1. 继承 Thread:直接继承并重写 run() 方法,适合简单场景,但无法继承其他类。
  2. 实现 Runnable 接口:实现 Runnable 接口的类并重写 run() 方法,适合共享任务的场景。
  3. 使用 CallableFutureCallable 可以返回结果并抛出异常,适合需要结果的任务,通过 Future 获取任务结果。
  4. 使用线程池:通过 ExecutorService 创建线程池,复用线程,提高性能,适合高并发场景。

在实际开发中,线程池是推荐的方式,因为它不仅可以有效管理线程,还能提高程序的性能和可扩展性。

相关文章:

Java 创建线程的方式有哪几种

在 Java 中&#xff0c;创建线程的方式有四种&#xff0c;分别是&#xff1a;继承 Thread 类、实现 Runnable 接口、使用 Callable 和 Future、使用线程池。以下是详细的解释和通俗的举例&#xff1a; 1. 继承 Thread 类 通过继承 Thread 类并重写 run() 方法来创建线程。 步…...

计算机的错误计算(一百八十七)

摘要 用大模型计算 sin(123.456789). 其自变量为弧度。结果保留16位有效数字。第一个大模型是数学大模型。先是只分析&#xff0c;不计算&#xff1b;后经提醒&#xff0c;才给出结果&#xff0c;但是是错误结果。第二个大模型&#xff0c;直接给出了Python代码与结果&#xf…...

12. 最大括号深度

题目描述 现有一字符串仅由"("&#xff0c;")", "{","}", "[", "]"六种括号组成。若字符串满足以下条件之一&#xff0c; 则为无效字符串:任一类型的左右括号数量不相等 存在未按正确顺序(先左后右)闭合的括号输出…...

进程与线程以及如何查看

长期补充&#xff0c;建议关注收藏&#xff01; 定义 特性进程线程定义程序执行的基本单位执行中的最小单位资源拥有独立的内存空间和资源共享进程的资源开销创建和销毁的开销较大创建和销毁的开销较小执行单位进程中可以有多个线程线程是执行单元&#xff0c;必须依赖于进程并…...

BlueLM:以2.6万亿token铸就7B参数超大规模语言模型

一、介绍 BlueLM 是由 vivo AI 全球研究院自主研发的大规模预训练语言模型&#xff0c;本次发布包含 7B 基础 (base) 模型和 7B 对话 (chat) 模型&#xff0c;同时我们开源了支持 32K 的长文本基础 (base) 模型和对话 (chat) 模型。 更大量的优质数据 &#xff1a;高质量语料…...

Webpack学习笔记(4)

1.缓存 可以通过命中缓存降低网络流量&#xff0c;是网站加站速度更快。 然而在部署新版本时&#xff0c;不更改资源的文件名&#xff0c;浏览器可能认为你没有更新&#xff0c;所以会使用缓存版本。 由于缓存存在&#xff0c;获取新的代码成为问题。 接下来将配置webpack使…...

28、论文阅读:基于像素分布重映射和多先验Retinex变分模型的水下图像增强

A Pixel Distribution Remapping and Multi-Prior Retinex Variational Model for Underwater Image Enhancement 摘要介绍相关工作基于模型的水下图像增强方法&#xff1a;无模型水下图像增强方法&#xff1a;基于深度学习的水下图像增强方法&#xff1a; 论文方法概述像素分布…...

5.interview-self-introduction

1.保证电话面试来的时候&#xff0c;可以接听&#xff0c;保持电话通常 interviews will be arranged recently.please keep your phone line open and make sure you can answer th call when the phone interview comes. speak loudly and slow down your speaking voice &a…...

高性能MySQL-查询性能优化

查询性能优化 1、为什么查询这么慢2、慢查询基础&#xff1a;优化数据访问2.1 是否向数据库请求了不需要的数据2.2 MySQL是否存在扫描额外的记录 3、重构查询方式3.1 一个复杂查询还是多个简单查询3.2 切分查询3.3 分解联接查询 4、查询执行的基础4.1 MySQL的客户端/服务器通信…...

如何有效修复ffmpeg.dll错误:一站式解决方案指南

当您遇到提示“ffmpeg.dll文件丢失”的错误时&#xff0c;这可能导致相关的应用程序无法启动或运行异常。本文将详细介绍如何有效地解决ffmpeg.dll文件丢失的问题&#xff0c;确保您的应用程序能够恢复正常运行。 ffmpeg.dll是什么&#xff1f;有哪些功能&#xff1f; ffmpeg.…...

8086汇编(16位汇编)学习笔记00.DEBUG命令使用解析及范例大全

8086汇编(16位汇编)学习笔记00.DEBUG命令使用解析及范例大全-C/C基础-断点社区-专业的老牌游戏安全技术交流社区 - BpSend.net[md]启动 Debug&#xff0c;它是可用于测试和调试 MS-DOS 可执行文件的程序。  Debug [[drive:][path] filename [parameters]]  参数  [drive:…...

查看mysql的冷数据配置比例

查看mysql的冷数据配置比例 -- 真正的LRU链表&#xff0c;会被拆分为两个部分&#xff0c;一部分是热数据&#xff0c;一部分是冷数据&#xff0c;这个冷热数据的比例是由innodb_old_blocks_pct参数控制的&#xff0c;它默认是37&#xff0c;也就是说冷数据占比37%。 show GLO…...

【Java基础面试题028】Java中的hashCode和equals方法,与==操作符有什么区别?

回答重点 hashcode、equals 和 都是Java中用于比较对象的三种方式&#xff0c;但是它们的用途和实现还是有挺大区别的。 hashcode用于散列存储结构中确定对象的存储位置。可用于快速比较两个对象是否不同&#xff0c;因为如果它们的哈希码不同&#xff0c;那么它们肯定不相等…...

在C#中测试比较目录的不同方法以查看它们有哪些共同的文件

C# 中的示例“比较目录以查看它们有哪些共同的文件”使用Directory.GetFiles获取两个目录中的文件。它对文件进行排序&#xff0c;并比较两个排序后的列表以查看哪些文件位于第一个目录中、第二个目录中或两个目录中。有关其工作原理的详细信息&#xff0c;请参阅该示例。 Kur…...

harbor离线安装 配置https 全程记录

1. 下载harbor最新版本 下载网址: 找最新的版本: https://github.com/goharbor/harbor/releases/download/v2.11.2/harbor-offline-installer-v2.11.2.tgz 这里我直接使用迅雷下载, 然后上传 1.1解压 sudo tar -xf harbor-offline-installer-v2.11.2.tgz -C /opt/ 2. 配置Harb…...

C++简明教程(文章要求学过一点C语言)(5)

在开始之前必须阅读这个文章 https://blog.csdn.net/weixin_45100742/article/details/135152562 这篇文章完全是对C语言的补课&#xff0c;如果C语言学的好&#xff0c;可跳过。 变量、数据类型与运算符 在 C 编程中&#xff0c;理解变量、数据类型和运算符是构建程序的基石…...

Halcon单相机+机器人=眼在手上#标定心得

首先&#xff0c;这个标定板肯定是放在我们要作业的工作台上的 目的 **1&#xff0c;得到标定物&#xff08;工作台&#xff09;与机器人底座之间的pose转换关系。2&#xff0c;得到相机与机器人末端tool的的转换关系。 两个不确定的定量 1&#xff0c;标定板与机器人底座b…...

【hackmyvm】Diophante 靶场

1. 基本信息^toc 这里写目录标题 1. 基本信息^toc2. 信息收集2.1. 端口扫描2.2. 目录扫描2.3. knock 3. WordPress利用3.1. wpscan扫描3.2. smtp上传后门 4. 提权4.1. 提权leonard用户4.2. LD劫持提权root 靶机链接 https://hackmyvm.eu/machines/machine.php?vmDiophante 作者…...

C++类的继承关系中什么时候要用到上行转换和下行转换

一、C类继承关系中的上行转换 1. 多态性实现 在C中&#xff0c;上行转换&#xff08;将派生类转换为基类&#xff09;是实现多态性的关键。例如&#xff0c;当有一个基类Animal&#xff0c;以及派生类Dog和Cat。如果有一个函数接受Animal类型的参数&#xff0c;我们可以将Dog或…...

Ubuntu 22.04永久保存路由

在 Ubuntu 22.04 上&#xff0c;可以按照以下方式配置让流量访问 172.19.201.207 走指定的路由。 1. 临时添加路由 临时路由规则只在当前系统会话中有效&#xff0c;重启后会丢失。 添加路由规则 运行以下命令&#xff1a; sudo ip route add 172.19.201.207 via 192.168.2…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

快刀集(1): 一刀斩断视频片头广告

一刀流&#xff1a;用一个简单脚本&#xff0c;秒杀视频片头广告&#xff0c;还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农&#xff0c;平时写代码之余看看电影、补补片&#xff0c;是再正常不过的事。 电影嘛&#xff0c;要沉浸&#xff0c;…...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...