news 2026/4/23 12:22:31

Java线程的三种创建方式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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. 合理使用线程池管理线程资源

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 12:25:21

Off-Page SEO权威清单:构建高质量外链与品牌声誉的完整体系

什么是Off-Page SEO&#xff1f; Off-Page SEO是指在网站外部采取的行动&#xff0c;以提升网站的权威性和可信度&#xff0c;这不仅能提升品牌声誉&#xff0c;还能在传统和AI搜索中获得可见度。 一些有助于建立强大在线存在感的 Off-Page SEO 策略包括&#xff1a; 从网络上有…

作者头像 李华
网站建设 2026/4/23 9:47:50

jQuery Mobile 主题

jQuery Mobile 主题 引言 jQuery Mobile 是一个流行的前端框架,用于创建响应式网站和应用程序。其核心特点之一就是主题,主题使得开发者能够快速定制界面风格,以适应不同的品牌和用户需求。本文将深入探讨 jQuery Mobile 主题的概念、类型、定制方法以及最佳实践。 jQuer…

作者头像 李华
网站建设 2026/4/23 9:48:14

ZingChart使用动画过渡效果使图表更清晰

使用动画过渡效果使图表更清晰 2025年12月15日Web Components 图表具有流畅的动画效果&#xff0c;使数据变化更容易查看&#xff0c;并帮助用户保持专注&#xff0c;即使是复杂的视觉效果。ZingChart Web Components 图表控件中的动画是指在数据渲染、更新或交互过程中应用于图…

作者头像 李华
网站建设 2026/4/23 9:51:00

AppML 案例模板

AppML 案例模板 引言 AppML,作为一款强大的移动应用开发工具,以其高效、便捷的特点受到了广大开发者的青睐。为了帮助开发者更好地理解和运用AppML,本文将提供一个案例模板,旨在指导开发者如何利用AppML创建出优秀的移动应用。 案例背景 随着移动互联网的快速发展,移动…

作者头像 李华
网站建设 2026/4/18 7:47:38

JavaScript如何利用JQuery实现100G文件HTTP断点续传?

大文件传输解决方案建议书 一、需求分析与技术挑战 作为福建IT行业软件公司项目负责人&#xff0c;针对贵司提出的大文件传输需求&#xff0c;我进行了全面分析&#xff0c;发现以下几个核心挑战&#xff1a; 超大文件传输稳定性&#xff1a;单文件100G的传输及断点续传文件…

作者头像 李华
网站建设 2026/4/23 9:50:20

JS如何利用切片技术实现超大附件的秒传与续传?

前端老哥的奇幻漂流&#xff1a;20G文件上传历险记 大家好&#xff0c;我是那个"预算100元想造航天飞机"的陕西前端老哥。最近接了个外包&#xff0c;客户要求用原生JS实现20G文件上传&#xff0c;还要兼容IE9…我差点没把手中的肉夹馍吓掉&#xff01; 需求分析&a…

作者头像 李华