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

多线程的三种实现方法

方式1:继承Thread类

代码特点:

class Mythread extends Thread {@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(getName() + "hello world");}}
}// 使用
public class ThreadDemo {public static void main(String[] args) {Mythread t1=new Mythread();Mythread t2=new Mythread();t1.setName("线程1");t2.setName("线程2");t1.start();t2.start();}
}

优点:

  • ✅ 简单直接:继承Thread类,重写run方法即可
  • ✅ 代码清晰:线程逻辑和线程对象在一起

缺点:

  • ❌ 单继承限制:Java只能单继承,限制了类的扩展性
  • ❌ 耦合度高:任务和线程绑定在一起
  • ❌ 资源浪费:每个任务都需要创建新的Thread对象

适用场景:

  • 简单的线程测试
  • 学习多线程基础概念
  • 不需要继承其他类的场景

方式2:实现Runnable接口

代码特点:

    /*
* 多线程第二种启动方式
* 1.自己定义一个类实现Runnable接口
* 2.重写里面的run方法
* 3.创建自己类的对象
* 4.创建一个Thread类对象,并开启线程
* */

class Myrun implements Runnable {@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName());}}
}public class ThreadDemo {public static void main(String[] args) {/** 多线程第二种启动方式* 1.自己定义一个类实现Runnable接口* 2.重写里面的run方法* 3.创建自己类的对象* 4.创建一个Thread类对象,并开启线程* *///创建Myrun的对象//表示多线程要执行的任务Myrun mr=new Myrun();//创建线程对象Thread t1=new Thread(mr);Thread t2=new Thread(mr);//给线程设置名字t1.setName("线程1");t2.setName("线程2");t1.start();t2.start();}
}

优点:

  • ✅ 灵活性强:可以继承其他类,实现多个接口
  • ✅ 资源共享:多个线程可以共享同一个Runnable对象
  • ✅ 符合面向接口编程:遵循"面向接口编程"原则
  • ✅ 支持Lambda表达式:代码更简洁

缺点:

  • ❌ 代码稍复杂:需要创建Thread对象
  • ❌ 无法直接获取线程信息:需要通过Thread.currentThread()

适用场景:

  • 日常开发中的多线程任务
  • 需要资源共享的场景
  • 符合面向对象设计原则的项目

方式3:实现Callable接口

代码特点:

/*
* 多线程的第三种实现方法
* 1.创建一个类MyCallable实现Callable接口
* 2.重写call(是有返回值的,表示多线程的运行结果)
* 3.创建MyCallable对象(表示多线程要执行的任务)
* 4..创建FutureTask的对象(作用管理多线程运行的结果)
* 5.创建Thread类的对象,并启动(表示线程)
*
* */
public class MyCallable implements Callable<Integer> {@Overridepublic Integer call() throws Exception {//求1-100的和int sum=0;for (int i = 0; i <= 100; i++) {sum+=i;}return sum;}
}
public class ThreadDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {MyCallable mc=new MyCallable();FutureTask<Integer> futureTask=new FutureTask<>(mc);Thread t1=new Thread(futureTask);t1.start();//获取多线程运行的结果Integer result=futureTask.get();System.out.println(result);}
}

优点:

  • ✅ 可以返回结果:call方法有返回值
  • ✅ 可以抛出异常:支持异常处理
  • ✅ 支持泛型:返回值类型灵活
  • ✅ 异步获取结果:通过FutureTask异步获取结果

缺点:

  • ❌ 使用复杂:需要FutureTask包装
  • ❌ 代码冗长:创建和使用过程较复杂
  • ❌ 阻塞获取:get()方法会阻塞等待结果

适用场景:

  • 需要返回值的计算任务
  • 需要异常处理的场景
  • 异步计算结果的获取
特性继承Thread实现Runnable实现Callable
复杂度最简单简单较复杂
继承限制只能单继承可以继承其他类可以继承其他类
返回值
异常处理不能抛出不能抛出可以抛出
资源共享不支持支持支持
推荐程度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

实际应用建议

1. 学习阶段:从继承Thread开始

  • 理解多线程基本概念
  • 掌握线程创建和启动

2. 日常开发:优先使用Runnable

  • 灵活性强,符合设计原则
  • 支持资源共享,效率高

3. 特殊需求:选择Callable

  • 需要返回值的计算任务
  • 需要异常处理的场景

总结:Runnable是最推荐的方式,既灵活又高效,适合大部分开发场景!

http://www.xdnf.cn/news/19819.html

相关文章:

  • C#基础(⑦user32.dll)
  • 各省市信息化项目管理办法中的网络安全等级保护如何规定的?
  • 前缀树约束大语言模型解码
  • 05 Centos 7尝试是否有网络
  • 深入浅出 RabbitMQ-RabbitMQ消息确认机制(ACK)
  • 解锁WebRTC在数字人领域的无限潜能
  • 【音视频】火山引擎实时、低延时拥塞控制算法的优化实践
  • centos系统如何判断是是x86还是x64?
  • ansible变量+管理机密
  • AV1 HEADERS详解
  • 专为 SOC 分析师和 MSSP 设计的威胁搜寻指南
  • flink中的窗口的介绍
  • mysql5.6+分页时使用 limit+order by 会出现数据重复问题
  • Mysql杂志(七)
  • Shell脚本入门:从零到精通
  • C# 原型模式(C#中的克隆)
  • “转”若惊鸿,电磁“通”——耐达讯自动化RS485转Profinet点亮能源新章
  • 【NestJS】HTTP 接口传参的 5 种方式(含前端调用与后端接收)
  • 【卷积神经网络】卷积神经网络的三大核心优势:稀疏交互、参数共享与等变表示
  • C++之基于正倒排索引的Boost搜索引擎项目介绍
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘black’问题
  • 【提示词】...(后续单元)在Prompt 的作用
  • 【linux仓库】万物至简的设计典范:如何用‘文件’这一个概念操纵整个Linux世界?
  • 在Docker中安装MySQL时3306端口占用问题
  • 论文学习30:LViT: Language Meets Vision Transformerin Medical Image Segmentation
  • 使用云手机进行游戏搬砖划算吗?
  • 国内真实的交换机、路由器和分组情况
  • 【保姆级喂饭教程】把chrome谷歌浏览器中的插件导出为CRX安装包
  • LeetCode 925.长按键入
  • 数据结构:希尔排序 (Shell Sort)