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

Java线程的三种创建方式

目录

1.线程的概念

2.进程和线程的对比

3.线程创建的三种方式

1)继承Thread类

2)实现Runnable接口

3)实现Callable接口

三种方法的执行流程


1.线程的概念

线程是程序执行流的最小单位,是进程中的一个独立执行单元。一个进程可以包含多个线程,这些线程共享进程的资源,但各自独立执行。


2.进程和线程的对比


3.线程创建的三种方式

1)继承Thread类

/** * 第一种创建线程的方式,继承Thread类 * 优点:代码简单 * 缺点:单继承的局限性,不能再继承其他的类 */ public class Demo1 { public static void main(String[] args) { Thread myThread= new MyThread(); myThread.start(); for (int i = 0; i < 6; i++) { System.out.println("main方法输出:"+ i); } } } class MyThread extends Thread { public void run() { for (int i = 0; i < 6; i++) { System.out.println("子线程输出:" + i); } } }

继承关系:MyThread extends Thread

重写方法:必须重写 run() 方法

启动方式:创建对象后调用 start() 方法

执行机制:

start() 会启动新线程,同时调用 run() 方法

直接调用 run() 只会普通方法调用,不会创建新线程

输出结果特点:主线程和子线程的输出会交替出现,顺序不确定

2)实现Runnable接口

/** * 第二种创建线程的方式:实现Runnable接口 * 优点:只是实现了接口,可以继承其他类,实现其他接口,拓展性强 * 缺点:需要多一个Runnable对象 */ public class Demo2 { // 目标:掌握多线程的第二种创建方式:实现runnable接口 public static void main(String[] args) { //3.创建线程对象,要把这个线程任务类包装成线程类,把这个对象交给线程去处理 Thread MyRunnable = new Thread(new MyRunnable()); MyRunnable.start(); for (int i = 0; i < 6; i++) { System.out.println("Main方法输出:" + i); } } } //1.定义一个线程任务类来实现Runnable接口 class MyRunnable implements Runnable { //2.重写run方法,执行线程任务 @Override public void run() { for (int i = 0; i < 6; i++) { System.out.println("子线程输出:" + i); } } }

实现关系:MyRunnable implements Runnable

重写方法:必须实现 run() 方法

线程创建:需要将 Runnable 对象传给 Thread 构造器

优点:

避免单继承限制

适合多个线程执行相同任务

代码结构更清晰

简化写法

1.匿名内部类
/** * 线程创建的第二种方法的匿名内部类写法 */ public class Demo3 { public static void main(String[] args) { // 使用匿名内部类创建Runnable对象 Thread t1 = new Thread(new Runnable(){ @Override public void run() { for (int i = 0; i < 6; i++) { System.out.println("子线程输出:" + i); } } }); t1.start(); for (int i = 0; i < 6; i++) { System.out.println("Main方法输出:" + i); } } }
2.lambda表达式
// Java 8+ 可以使用Lambda表达式进一步简化 public class Demo2_Lambda { public static void main(String[] args) { // 使用Lambda表达式创建Runnable对象 Thread thread = new Thread(() -> { for (int i = 0; i < 6; i++) { System.out.println("子线程输出:" + i); } }); thread.start(); for (int i = 0; i < 6; i++) { System.out.println("Main方法输出:" + i); } } }

3)实现Callable接口

import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; /** * 前面两种创建方式重写的run方法都不能直接返回结果 * JDK5.0提供了Callable接口和FutureTask类来实现 * 第三种创建方式 */ public class Demo4 { public static void main(String[] args) { // 创建Callable接口的实现类对象 Callable<String> c = new MyCallable(100); // 4. 把Callable对象封装成真正的线程任务对象FutureTask对象 FutureTask<String> ft = new FutureTask<>(c); /** * FutureTask对象的作用 * a. 本质是一个Runnable线程任务对象,可以交给Thread线程对象处理 * b. 可以获取线程执行完毕后的结果 */ // 5. 把FutureTask对象作为参数传递给Thread对象 Thread thread = new Thread(ft); thread.start(); // 启动线程 // 创建第二个线程 Callable<String> c1 = new MyCallable(300); FutureTask<String> ft1 = new FutureTask<>(c1); Thread thread1 = new Thread(ft1); thread1.start(); try { // 获取第一个线程的执行结果 // get()方法会阻塞,直到线程执行完成并返回结果 System.out.println(ft.get()); } catch (Exception e) { e.printStackTrace(); } try { // 获取第二个线程的执行结果 System.out.println(ft1.get()); } catch (Exception e) { e.printStackTrace(); } } } // 1. 定义实现类来实现Callable接口 // 泛型参数表示返回值的类型 class MyCallable implements Callable<String> { private Integer n; // 构造方法,传入计算范围 MyCallable(Integer n) { this.n = n; } // 2. 重写call方法,有返回值,可以抛出异常 @Override public String call() throws Exception { Integer sum = 0; for (int i = 1; i <= n; i++) { sum += i; } return "1+.....+" + n + "的输出结果为" + sum; } }

实现关系:MyCallable implements Callable<String>

重写方法:必须实现 call() 方法

关键区别:

call() 方法可以有返回值

call() 方法可以抛出异常

run() 方法没有返回值,不能抛出检查异常

执行流程:
Callable实现类 → FutureTask包装 → Thread包装 → start()启动 → get()获取结果
FutureTask 的作用:

适配器模式:将 Callable 转换成 Runnable

结果容器:存储异步计算结果

阻塞获取:get() 方法会等待线程执行完成

三种方法的执行流程

// 方式1:继承Thread Thread子类 → start() → JVM调用run() // 方式2:实现Runnable Runnable实现类 → 传给Thread → start() → JVM调用run() // 方式3:实现Callable Callable实现类 → FutureTask包装 → 传给Thread → start() → get()获取结果

小结

  1. 优先选择实现 Runnable 接口,配合 Lambda 表达式

  2. 需要返回值时使用 Callable + FutureTask

  3. 避免直接继承 Thread 类

  4. 合理使用线程池管理线程资源

http://www.cnnetsun.cn/news/115788.html

相关文章:

  • 国内容易上手的claudecode一键配置指南
  • 复原IP地址
  • Redis 发布订阅
  • JQuery支持WebUploader完成百万文件断点续传的原理?
  • Vue3如何结合组件实现大文件分片的并行上传优化?
  • 类型分布统计-Cordovaopenharmony多维分析实战
  • 四时四名,一山万象:朝鲜金刚山的锦绣风姿
  • 基于Spring Boot的果蔬销售系统
  • Scala Collection(集合)
  • 介观交通流仿真软件:DynusT_(11).交通事件管理
  • django基于Python天气分析系统
  • python基于大数据的分析长沙旅游景点推荐系统
  • 基于Django的学分管理系统
  • 广度优先遍历与最短路径
  • 通信系统仿真:通信系统基础理论_(11).光通信技术
  • 17、Linux文件与目录操作全解析
  • 21、Linux系统进程与包管理全解析
  • 二叉排序树的插入、先序/中序/后序/层次遍历、节点查询
  • 如何在 Spring Boot 中接入 Amazon ElastiCache
  • 基于51单片机的血糖步数测量仪
  • Linux C/C++ 学习日记(51):内存池
  • AAAI25|基于神经共形控制的时间序列预测模型
  • CATCH:ICLR 2025 最值得关注的时间序列异常检测新框架
  • 开发到生产全链路:Docker containerd Kubernetes 运行时全景指南
  • 文件包含漏洞终极指南
  • #扫雷游戏
  • Java计算机毕设之基于springboot+vue的高校学院校内订餐系统的设计与实现基于JAVA的学院校内订餐系统的实现(完整前后端代码+说明文档+LW,调试定制等)
  • 小程序计算机毕设之基于微信跑腿小程序的设计与实现基于springboot+微信小程序的跑腿小程序的设计与实现(完整前后端代码+说明文档+LW,调试定制等)
  • 小程序计算机毕设之基于springboot+微信小程序的餐厅预约系统设计与实现基于微信小程序的餐厅预约系统设计与实现(完整前后端代码+说明文档+LW,调试定制等)
  • torch报错:ibtorch_cpu.so: cannot enable executable stack as shared object requires: Invalid argument