Java——》创建线程的方式

推荐链接:
    总结——》【Java】
    总结——》【Mysql】
    总结——》【Redis】
    总结——》【Kafka】
    总结——》【Spring】
    总结——》【SpringBoot】
    总结——》【MyBatis、MyBatis-Plus】
    总结——》【Linux】
    总结——》【MongoDB】
    总结——》【Elasticsearch】

Java——》创建线程的方式

  • 1. 继承Thread类,重写run方法
    • 1.1 步骤
    • 1.2 示例
    • 1.3 注意
  • 2. 实现Runnable接口,重写run方法
    • 2.1 步骤
    • 2.2 示例
    • 2.3 优点
  • 3. 实现Callable接口,重写call方法,配合FutureTask
    • 3.1 步骤
    • 3.2 示例
    • 3.3 底层实现
    • 3.4 Future对象
    • 3.5 实现Runnable接口和实现Callable接口的区别
  • 4. 基于线程池创建线程
  • 5. 总结

Java中的线程本质上就是一个Thread对象

创建线程常用方式:

  1. 继承Thread类,重写run方法
  2. 实现Runnable接口
  3. 实现Callable接口
  4. 线程池

1. 继承Thread类,重写run方法

1.1 步骤

  1. 创建Thread类的子类
  2. 重写run()方法
  3. 创建线程对象
  4. 调用start()方法,启动线程

1.2 示例

package org.example;public class CreateThreadForThread {public static void main(String[] args) {System.out.println("main方法执行开始...");// Java中的线程本质上就是一个Thread对象Thread t1 = new MyThread();/*start()方法:1. 启动一个新的线程2. 线程不能启动多次,否则报异常3. 实际下真正开启线程的是CPU,当CPU空闲或分配到此任务的时候,就会创建一个新的线程,然后执行run()方法中的代码*/t1.start();// 如果要创建多个线程,需要创建多个Thread对象Thread t2 = new MyThread();t2.start();Thread t3 = new MyThread();// 显示的调用Thread的run()方法,并没有开启新的线程t3.run();for (int i = 0; i < 100; i++) {System.out.println("main方法的循环..." + i);}System.out.println("main方法执行结束...");}
}
/*** 继承Thread类,重写run方法*/
class MyThread extends Thread{@Overridepublic void run() {System.out.println("子线程执行开始....");for(int i = 0 ; i < 10 ; i ++){System.out.println("子线程的循环:"+i);}System.out.println("子线程执行结束....");}
}

1.3 注意

  1. 启动线程是使用start()方法而不是run()方法
  2. 调用run()方法,当前线程直接执行run()方法中的业务逻辑
  3. 线程不能启动多次
  4. 如果要创建多个线程,需要创建多个Thread对象

2. 实现Runnable接口,重写run方法

2.1 步骤

  1. 创建Runable的实现类
  2. 重写run方法
  3. 创建Runable实例对象(通过实现类来实现)
  4. 创建Thread对象,并把第3步的Runable实现作为Thread构造方法的参数
  5. 调用start方法,启动线程

2.2 示例

package org.example;/*** 创建线程对象:* 方式1:通过Runable实现接口* 方式2:通过Runable匿名内部类* 方式3:通过lambda表达式*/
public class CreateThreadForRunnable {public static void main(String[] args) {System.out.println("main方法执行开始...");MyRunnable myRunnable = new MyRunnable();// 方式1:创建Thread对象的时候传递了一个Runable接口实现Thread t1 = new Thread(myRunnable);// 启动线程t1.start();// 方式2:创建Thread对象的时候传递了一个Runable匿名内部类Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println("匿名内部类的循环:" + i);}}});t2.start();// 方式3:创建Thread对象的时候传递了一个lambda表达式Thread t3 = new Thread(() -> {for (int i = 0; i < 100; i++) {System.out.println("lambda的循环:" + i);}});t3.start();for (int i = 0; i < 100; i++) {System.out.println("main方法的循环..." + i);}System.out.println("main方法执行结束...");}}/*** 实现Runnable接口,重写run方法*/
class MyRunnable implements Runnable{@Overridepublic void run() {System.out.println("子线程执行开始....");for (int i = 0; i < 100; i++) {System.out.println("子线程的循环:"+i);}System.out.println("子线程执行结束....");}
}

2.3 优点

  1. 可以避免Java单继承带来的局限性
  2. 适合多个相同的程序代码处理同一个资源的情况,把线程同程序的代码和数据有效的分离,较好的体现了面向对象的设计思想

3. 实现Callable接口,重写call方法,配合FutureTask

前面介绍的两种创建线程的方式都是重写run()方法,而且run()方法是没有返回结果的,也就是main方法是不知道开启的线程什么时候开始执行,什么时候结束执行,也获取不到对应的返回结果。而且run()方法也不能把可能产生的异常抛出。

JDK1.5之后,推出了通过实现Callable接口的方式来创建新的线程,这种方式可以获取对应的返回结果。

3.1 步骤

  1. 创建Callable的实现类
  2. 重写call()方法
  3. 创建Callable实例对象(通过实现类来实现)
  4. 创建FutureTask实例对象,传入Callable实例对象
  5. 创建Thread实例对象,传入FutureTask实例对象作为Thread构造方法的参数
  6. 调用start方法,启动线程

3.2 示例

package org.example;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class CreateThreadForCallable {public static void main(String[] args) throws ExecutionException, InterruptedException {System.out.println("main方法执行开始...");//1. 创建MyCallableCallable<Integer> myCallable = new MyCallable();//2. 创建FutureTask,传入CallableFutureTask<Integer> futureTask = new FutureTask<Integer>(myCallable);//3. 创建Thread线程, futureTask本质上是Runable接口的实现Thread t1 = new Thread(futureTask);//4. 启动线程,本质上是执行Runable中的run()方法,只是run()方法中调用了call()方法t1.start();//5. 做一些操作//6. 线程执行完成后返回的结果Integer count = futureTask.get();System.out.println("总和为:" + count);System.out.println("main方法执行结束...");}
}/*** 创建Callable的实现类* 指定Callable的泛型,这个泛型是返回结果的类型*/
class MyCallable implements Callable<Integer> {@Overridepublic Integer call() throws Exception {System.out.println("子线程执行开始....");int count = 0;for (int i = 0; i < 100; i++) {count += i;}System.out.println("子线程执行结束....");return count;}
}

3.3 底层实现

其实Callable接口底层的实现就是**对Runable接口实现的封装**,线程启动后执行的也是Runable接口实现中的run()方法,只是在run()方法中有调用call()方法。

3.4 Future对象

运行Callable任务可以拿到一个Future对象,表示**异步计算的结果**。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。

3.5 实现Runnable接口和实现Callable接口的区别

区别实现Runnable接口实现Callable接口
版本JDK1.1之后JDK1.5之后
规定方法run()call()
返回值有,Future.get()
抛出异常不可以可以
加入线程池运行ExecutorService.execute()ExecutorService.submit()

4. 基于线程池创建线程

追其底层,其实只有一种,实现Runnble

package org.example;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ExecutorServiceTest {public static void main(String[] args) {ExecutorService service = Executors.newCachedThreadPool();service.execute(() -> {System.out.println("Hello ThreadPool");});}
}

5. 总结

package org.example;import java.util.concurrent.*;public class CreateThread {public synchronized void m1() {System.out.println(Thread.currentThread().getName() + " m1 ");}static class MyThread extends Thread {@Overridepublic void run() {System.out.println("Hello MyThread!");}}static class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("Hello MyRunnable!");}}// 需要指定Callable的泛型,这个泛型是返回结果的类型static class MyCallable implements Callable<String> {@Overridepublic String call() throws Exception {System.out.println("Hello MyCallable");return "success";}}public static void main(String[] args) throws Exception {// 第1种:继承Thread类,重写run方法new MyThread().start();// 第2种:实现Runnable接口,重写run方法new Thread(new MyRunnable()).start();// 本质是创建Thread对象的时候传递了一个Runable接口实现// 第3种:匿名内部类,重写run方法new Thread(new Runnable(){@Overridepublic void run() {System.out.println("Hello Runnable!");}}).start();// 第4种:lamda表达式new Thread(() -> {System.out.println("Hello Lambda!");}).start();// 第5种:实现Callable接口,重写call方法(运行 + 返回值)FutureTask<String> task = new FutureTask<>(new MyCallable());// FutureTask 本质上是 Runable 接口的实现Thread t = new Thread(task);t.start();// 本质还是执行 Runable中的run方法,只是 run方法调用了call方法System.out.println(task.get());// 获取线程执行完成后返回的结果ExecutorService service = Executors.newCachedThreadPool();// 第6种:线程池,无返回值service.execute(() -> {System.out.println("Hello ThreadPool");});// 第7种:线程池,有返回值Future<String> f = service.submit(new MyCallable());String s = f.get();System.out.println(s);service.shutdown();CreateThread tt = new CreateThread();//1.8之前的写法new Thread(new Runnable() {@Overridepublic void run() {tt.m1();}}).start();//1.8之后的写法:默认线程名称new Thread(()->tt.m1()).start();new Thread(tt::m1).start();//1.8之后的写法:自定义线程名称new Thread(()->tt.m1(), "t1").start();new Thread(tt::m1, "t1").start();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/59980.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

集群架构中Lua脚本的限制以及出现的报错

&#x1f680; 博主介绍&#xff1a;大家好&#xff0c;我是无休居士&#xff01;一枚任职于一线Top3互联网大厂的Java开发工程师&#xff01; &#x1f680; &#x1f31f; 在这里&#xff0c;你将找到通往Java技术大门的钥匙。作为一个爱敲代码技术人&#xff0c;我不仅热衷…

大语言模型:解锁自然语言处理的无限可能

0.引言 在当今的科技时代&#xff0c;自然语言处理技术正以前所未有的速度发展&#xff0c;语言大模型作为其中的核心力量&#xff0c;对各个领域产生了深远的影响。本文旨在探讨语言大模型的发展历程、核心技术以及广泛的应用场景&#xff0c;以帮助读者更好地理解这一前沿技…

MATLAB实现智能水滴算法(Intelligent Water Drops Algorithm, IWDA)

1.智能水滴算法介绍 智能水滴算法&#xff08;Intelligent Water Drops Algorithm&#xff0c;IWDA&#xff09;是一种基于水滴特性的智能优化算法&#xff0c;它借鉴了水滴在自然界中的运动和形态变化规律&#xff0c;通过模拟水滴的形成、发展和消亡过程&#xff0c;实现问题…

【计网】基于TCP协议的Echo Server程序实现与多版本测试

目录 前言&#xff1a; 1、InitServer类的实现 1.1. 创建流式套接字 1.2. bind 绑定一个固定的网络地址和端口号 1.3.listen监听机制 1.4.完整代码 2. 循环接收接口与服务接口 2.1.accept函数讲解 讲个商场拉客的故事方便我们理解&#xff1a; 2.2.服务接口实现 3.服…

easyexcel实现自定义的策略类, 最后追加错误提示列, 自适应列宽,自动合并重复单元格, 美化表头

easyexcel实现自定义的策略类, 最后追加错误提示列, 自适应列宽,自动合并重复单元格, 美化表头 原版表头和表体字体美化自动拼接错误提示列自适应宽度自动合并单元格使用Easyexcel使用poi导出 在后台管理开发的工作中,离不开的就是导出excel了. 如果是简单的导出, 直接easyexce…

边缘计算的学习

文章目录 概要何为边缘计算&#xff1f;现阶段&#xff0c;企业使用边缘计算相对云计算 整体架构流程边缘网络组件边缘计算与云安全 研究方向结合引用 概要 edge 何为边缘计算&#xff1f; 边缘计算&#xff08;英语&#xff1a;Edge computing&#xff09;&#xff0c;是一种…

SpringBoot在城镇保障性住房管理中的应用

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理城镇保障性住房管理系统的相关信息成为必然…

算法|牛客网华为机试41-52C++

牛客网华为机试 上篇&#xff1a;算法|牛客网华为机试21-30C 文章目录 HJ41 称砝码HJ42 学英语HJ43 迷宫问题HJ44 SudokuHJ45 名字的漂亮度HJ46 截取字符串HJ48 从单向链表中删除指定值的节点HJ50 四则运算HJ51 输出单向链表中倒数第k个结点HJ52 计算字符串的编辑距离 HJ41 称砝…

粒子群优化双向深度学习!PSO-BiTCN-BiGRU-Attention多输入单输出回归预测

粒子群优化双向深度学习&#xff01;PSO-BiTCN-BiGRU-Attention多输入单输出回归预测 目录 粒子群优化双向深度学习&#xff01;PSO-BiTCN-BiGRU-Attention多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现PSO-BiTCN-BiGRU-Attention粒子…

「Mac玩转仓颉内测版1」入门篇1 - Cangjie环境的搭建

本篇详细介绍在Mac系统上快速搭建Cangjie开发环境的步骤&#xff0c;涵盖VSCode的下载与安装、Cangjie插件的离线安装、工具链的配置及验证。通过这些步骤&#xff0c;确保开发环境配置完成&#xff0c;为Cangjie项目开发提供稳定的基础支持。 关键词 Cangjie开发环境搭建VSC…

协程6 --- HOOK

文章目录 HOOK 概述链接运行时动态链接 linux上的常见HOOK方式修改函数指针用户态动态库拦截getpidmalloc 第一版malloc 第二版malloc/free通过指针获取到空间大小malloc 第三版strncmp 内核态系统调用拦截堆栈式文件系统 协程的HOOK HOOK 概述 原理&#xff1a;修改符号指向 …

ResNet 残差网络 (乘法→加法的思想 - 残差连接是所有前沿模型的标配) + 代码实现 ——笔记2.16《动手学深度学习》

目录 前言 0. 乘法变加法的思想 1. 函数类 2. 残差块 (讲解代码) QA: 残差这个概念的体现&#xff1f; 3. ResNet模型 (代码讲解) 补充&#xff1a;更多版本的ResNet 4. 训练模型 5. 小结 6. ResNet的两大卖点 6.1 加深模型可以退化为浅层模型 6.2 用加法解决梯度消…

iphone怎么删除重复的照片的新策略

Phone用户常常面临存储空间不足的问题&#xff0c;其中一个主要原因是相册中的重复照片。这些重复项不仅占用了大量的存储空间&#xff0c;还会影响设备的整体性能。本文将向您展示iphone怎么删除重复的照片的方法&#xff0c;包括一些利用工具来自动化这个过程的创新方法。 识…

软件缺陷等级评定综述

1. 前言 正确评估软件缺陷等级&#xff0c;在项目的生命周期中有着重要的作用&#xff1a; 指导缺陷修复的优先级和资源分配 在软件开发和维护过程中&#xff0c;资源&#xff08;包括人力、时间和资金&#xff09;是有限的。通过明确缺陷的危险等级&#xff0c;可以帮助团队合…

【Pikachu】Cross-Site Scripting跨站脚本攻击实战

只管把目标定在高峰&#xff0c;人家要笑就让他去笑&#xff01; 1.XSS&#xff08;跨站脚本&#xff09;概述 XSS&#xff08;跨站脚本&#xff09;概述 Cross-Site Scripting 简称为“CSS”&#xff0c;为避免与前端叠成样式表的缩写"CSS"冲突&#xff0c;故又称…

【SpringBoot】 黑马大事件笔记-day2

目录 用户部分 实体类属性的参数校验 更新用户密码 文章部分 规定josn日期输出格式 分组校验 上期回顾&#xff1a;【SpringBoot】 黑马大事件笔记-day1 用户部分 实体类属性的参数校验 对应的接口文档&#xff1a; 基本信息 请求路径&#xff1a;/user/update 请求方式&#…

大数据面试题--kafka夺命连环问

1、kafka消息发送的流程&#xff1f; 在消息发送过程中涉及到两个线程&#xff1a;一个是 main 线程和一个 sender 线程。在 main 线程中创建了一个双端队列 RecordAccumulator。main 线程将消息发送给双端队列&#xff0c;sender 线程不断从双端队列 RecordAccumulator 中拉取…

QT信号和槽与自定义的信号和槽

QT信号和槽与自定义的信号和槽 1.概述 这篇文章介绍下QT信号和槽的入门知识&#xff0c;通过一个案例介绍如何创建信号和槽&#xff0c;并调用他们。 2.信号和槽使用 下面通过点击按钮关闭窗口的案例介绍如何使用信号和槽。 创建按钮 在widget.cpp文件中创建按钮代码如下 …

unity显示获取 年月日周几【日期】

unity显示获取 年月日周几【日期】 public void ShowDate(Text txt){//txt.text DateTime now DateTime.Now; // 获取当前时间int year now.Year; // 获取年份int month now.Month; // 获取月份&#xff08;1-12&#xff09;int day now.Day; // 获取天数&#xff08;1-31&…

emr上使用sparkrunner运行beam数据流水线

参考资料 https://time.geekbang.org/column/intro/167?tabcatalog Apache Beam和其他开源项目不太一样&#xff0c;它并不是一个数据处理平台&#xff0c;本身也无法对数据进行处理。Beam所提供的是一个统一的编程模型思想&#xff0c;而我们可以通过这个统一出来的接口来编…