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

JavaWeb3-线程的3种创建方式7种写法

目录

1.方式一:继承Thread(2种写法)

写法①(常规):

a.使用jconsole观察线程

b.启动线程——start方法

PS:(常见面试题)start 方法与 run 方法的区别:

写法②(简化):匿名方式创建子对象

2.方式二:实现Runnable接口(3种写法)

写法③(常规):

写法④(变种):匿名Runnable方式(匿名内部类)

写法⑤(变种):使用Lambda匿名Runable方式(更简单)

3.方式三:实现Callable接口(带返回值可为任意类型)(2种写法)

写法⑥(常规):Callable + FutureTask(一个容器,用来接收线程执行的返回值)

写法⑦(简单):匿名Callable


1.方式一:继承Thread(2种写法)

写法①(常规):

/*** 继承 Thread 创建线程*/
public class ThreadDemo3 {public static void main(String[] args) {//获得当前的线程Thread mainThread = Thread.currentThread();System.out.println("主线程的名称:" + mainThread.getName());//创建线程Thread thread = new MyThread();//开启线程thread.start();}
}class MyThread extends Thread {@Override //需要重写run方法public void run() {//具体的业务执行代码Thread thread = Thread.currentThread(); //得到当前运行的线程try {Thread.sleep(60 * 60 * 1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程的名称:" + thread.getName()); //打印当前线程的名称}
}

a.使用jconsole观察线程

启动上面程序后:

b.启动线程——start方法

  • 通过覆写 run ⽅法创建⼀个线程对象,但线程对象被创建出来并不意味着线程就开始运⾏了。(相当于提供给线程要做的事情的指令清单。 线程对象可以认为是把李四、王五叫过来了)
  • 调⽤ start ⽅法, 才真的在操作系统的底层创建出⼀个线程。 就是喊⼀声:”⾏动起来!“,线程才真正独⽴去执⾏了)

PS:(常见面试题)start 方法与 run 方法的区别:

public class ThreadDemo3 {public static void main(String[] args) {//创建线程Thread thread = new MyThread();//开启线程thread.start();
//        thread.run();}
}class MyThread extends Thread {@Overridepublic void run() {System.out.println("你好,线程");}
}

二者执行结果都是:

二者具体区别:

区别一:【方法性质不同】run 是一个普通方法,而 start 是开启新线程的方法。

  • 调用 run 方法相当于执行普通方法 run,其实是调用当前主程序 main 来执行方法体的,(所有的main方法都会创建一个名为main的线程)并不会开启新线程;
  • 而调用 start 方法是真正开启一个新线程来执行任务。
public class ThreadDemo3 {public static void main(String[] args) {//创建线程Thread thread = new MyThread();//开启线程thread.start();
//        thread.run();}
}class MyThread extends Thread {@Overridepublic void run() {Thread thread = Thread.currentThread();System.out.println(thread.getName());}
}

start:

run:

区别二:【执行速度不同】调用 run 方法会立即执行任务,调用 start 方法是将线程的状态改为就绪状态,不会立即执行。

  • run 方法也叫做线程体,它里面包含了具体要执行的业务代码,当调用 run 方法时,会立即执行 run 方法中的代码(如果当前线程时间片未用完);
  • 而调用 start 方法时,是启动一个线程并将线程的状态设置为就绪状态,并不会立即执行。

区别三:【调用次数不同】run 方法可以被重复调用,而 start 方法只能被调用一次。

  • 因为 run 方法是普通方法,而普通方法是可以被多次调用的,所以 run 方法可以被调用多次;
  • 而start 方法是创建新线程来执行任务,因为线程只能被创建一次,且线程状态是不可逆的。当线程调用了第一个 start 方法之后,线程的状态就会从新建状态 NEW,变为就绪状态 RUNNABLE,此时再次调用 start 方法,JVM 就会判断出当前的线程已经不等于新建状态,从而抛出 IllegalThreadStateException 非法线程状态异常。

start方法源码:

【Thread 在 start 的实现源码中做了判断看当前线程的状态是不是等于 0,也就是是否为新建状态NEW,如果线程不是新建状态 NEW,则会抛出非法线程状态异常 IllegalThreadStateException。】

public class ThreadDemo3 {public static void main(String[] args) {//创建线程Thread thread = new MyThread(); //NEW新建状态//开启线程thread.run(); //RUNABLE运行状态thread.run();thread.run();thread.start();thread.start();thread.start();}
}class MyThread extends Thread {@Overridepublic void run() {Thread thread = Thread.currentThread();System.out.println(thread.getName());}
}

写法②(简化):匿名方式创建子对象

public class ThreadDemo6 {public static void main(String[] args) {//创建线程并初始化Thread thread = new Thread() {@Overridepublic void run() {Thread t = Thread.currentThread();System.out.println("任务执行:" + t.getName());}};//执行线程thread.start();}
}

写法和↓类似:

List<String> list = new ArrayList<String>() {{add("ddd");
}};

继承Thread新建线程的缺点:Java 是单继承,继承了 Thread 就不能继承其他类了;然⽽ Java 可以实现多个接⼝,于是有了下⼀种⽅式。

2.方式二:实现Runnable接口(3种写法)

写法③(常规):

/*** 实现Runnable接口新建线程*/
public class ThreadDemo4 {public static void main(String[] args) {// Runnable不是Thread的子类,所以不能用之前的方式直接new一个MyThread2()// 而Thread类可以接收一个Runnable接口作为它的入参//创建RunnableMyThread2 myThread2 = new MyThread2();//创建一个线程Thread thread = new Thread(myThread2);//启动线程thread.start();}
}class MyThread2 implements Runnable {@Overridepublic void run() {//具体的业务代码Thread thread = Thread.currentThread(); //得到当前线程System.out.println("线程执行:" + thread.getName());}
}

写法④(变种):匿名Runnable方式(匿名内部类)

/*** Runnable匿名内部类来创建*/
public class ThreadDemo5 {public static void main(String[] args) {//匿名内部类Thread thread = new Thread(new Runnable() {@Overridepublic void run() {//业务代码Thread t = Thread.currentThread();System.out.println("执行任务:" + t.getName());}});//启动线程thread.start();}
}

写法⑤(变种):使用Lambda匿名Runable方式(更简单)

/*** 使用 lambda 来创建 Runnable*/
public class ThreadDemo7 {public static void main(String[] args) {//创建线程Thread thread = new Thread(() -> {//具体业务Thread t = Thread.currentThread();System.out.println("任务执行:" + t.getName());});//启动线程thread.start();}
}

进入Lambda表达式查看源码:

Lambda表达式是对于Runnable这个FunctionalInterface的一个实例化。

注:以上简单&变种支持JDK1.8+版本。

以上5种写法的共同问题:都没有返回值,当线程执行完成之后,主线程没法拿到新线程的执行结果。

3.方式三:实现Callable接口(带返回值可为任意类型)(2种写法)

写法⑥(常规):Callable + FutureTask(一个容器,用来接收线程执行的返回值)

Runnable(JDK1.0)比Callable(JDK1.5)诞生得早,后来当需要拿到线程的返回值时(使用频率低),为了不增加学习成本,改动原有Thread写法,新创建了FutureTask来接收线程执行的返回值。

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;/*** 实现Callable新建线程*/
public class ThreadDemo8 {public static void main(String[] args) throws ExecutionException, InterruptedException {//创建Callable实例MyCallable myCallable = new MyCallable();//用于接收Callable结果的对象FutureTask<Integer> futureTask = new FutureTask<>(myCallable);//创建新线程Thread thread = new Thread(futureTask); //Thread线程只能接收2种类型的参数,要么是Runnable,要么是FutureTask,不能直接接收一个Callable对象//启动线程thread.start();//接收新线程执行的结果int result = futureTask.get();System.out.println(Thread.currentThread().getName() + "——新线程返回的结果为:" + result);}
}/*** Callable<V> 泛型里面可以是任意数据类型*/
class MyCallable implements Callable<Integer> {@Overridepublic Integer call() throws Exception {//生成随机数的范围是0-9int randomNum = new Random().nextInt(10);System.out.println(Thread.currentThread().getName() + "——随机数:" + randomNum);return randomNum;}
}

写法⑦(简单):匿名Callable

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class ThreadDemo9 {public static void main(String[] args) throws ExecutionException, InterruptedException {FutureTask<String> futureTask = new FutureTask<>(new Callable<String>() {@Overridepublic String call() throws Exception {//新线程执行的业务代码String[] arrs = new String[]{"Java", "MySQL","Thread"};//随机返回一个字符串String result = arrs[new Random().nextInt(3)];System.out.println(Thread.currentThread().getName() + "——字符串:" + result);return result;}});//创建新线程Thread thread = new Thread(futureTask);//启动线程thread.start();String result = futureTask.get();System.out.println(Thread.currentThread().getName() + "——新线程的返回值:" + result);}
}

  • 如果是 JDK 1.8 以上版本(含1.8),在不需要获得线程执⾏结果的情况下,推荐使⽤写法②匿名方式创建子对象或写法⑤Lambda ⽅式来创建线程,因为简洁。
  • 如果想要获取线程执⾏结果,推荐使用写法⑦ FutureTask + Callable 的⽅式来实现。

相关文章:

JavaWeb3-线程的3种创建方式7种写法

目录 1.方式一&#xff1a;继承Thread&#xff08;2种写法&#xff09; 写法①&#xff08;常规&#xff09;&#xff1a; a.使用jconsole观察线程 b.启动线程——start方法 PS&#xff1a;&#xff08;常见面试题&#xff09;start 方法与 run 方法的区别&#xff1a; 写…...

驱动调试手段

文章目录 前言一、通过sysfs调试LCD查看电源:查看 pwm 信息查看管脚信息总结前言 本文记录在驱动中常用的调试手段 提示:以下是本篇文章正文内容,下面案例可供参考 一、通过sysfs 系统起来之后可以读取 sysfs 一些信息,来协助调试 示例: 调试LCD 输入如下命令 cat /…...

[RK3568 Android12] 音频及路由

1:概述(耳机 ,hdmiin ,板载喇叭) 在开发板上面,系统注册了三个音频输出通道,如下: [ 2.280612] ALSA device list: [ 2.280622] #0: rockchip,rk809-codec [ 2.280630] #1: ROCKCHIP,SPDIF [ 2.280638] #2: rockchip,hdmi console:/proc/asound # cat pcm …...

C++——C++11 第一篇

目录 统一的列表初始化 &#xff5b;&#xff5d;初始化 decltype ​编辑 nullptr STL中一些变化 右值引用和移动语义 左值引用和右值引用 总结 左值引用优缺点 右值引用&#xff08;将亡值&#xff09; 拷贝赋值和移动赋值 万能引用|完美转发 移动构造和移动赋值注意…...

Spring Data JPA 中 CrudRepository 和 JpaRepository 的区别

1 问题描述Spring Data JPA 中&#xff0c;CrudRepository 和 JpaRepository 有何区别&#xff1f;当我在网上找例子的时候&#xff0c;发现它们可以互相替换使用。它们有什么不同呢&#xff1f;为什么你习惯用其中的一个而不是另一个呢&#xff1f;2 CrudRepository 和 JpaRep…...

推荐几款好用的数据库管理工具

本文主要介绍几款常用的数据库管理软件&#xff08;客户端&#xff09;&#xff0c;包括开源/免费的、商用收费的&#xff0c;其中有一些是专用于 MySQL 数据库的&#xff0c;例如 MySQL Workbench、phpMyAdmin&#xff0c;有一些是支持多种 SQL、NoSQL 数据库的&#xff0c;例…...

DPDK — 性能优化手段

目录 文章目录 目录硬件布局层面的优化操作系统层面的优化Linux 操作系统版本应用程序层面的优化Cache 优化内存对齐内存预取SIMD 报文批处理DDIO使用高级 CPU 指令集硬件布局层面的优化 DPDK 在硬件布局层面的优化,主要体现在以下几个方面: CPU 频率的高低:CPU 频率越高,…...

Fedora Linux未来五年规划

Fedora 委员会一直致力于起草战略计划&#xff0c;以帮助 Fedora Linux 更好地发展。近日 Fedora 委员会公布了一份 “《未来五年的 Fedora Linux 》” 战略计划草案&#xff0c;这份草案里面包含了他们的雄心壮志&#xff1a;每周将 Fedora 的活跃贡献者人数增加一倍。 Fedora…...

【C++之容器篇】map和set常见函数接口的使用与剖析

目录前言一、set1. 简介2. 成员类型3. 构造函数(1) set()(2)set(InputIterator first,InputIterator last)(3)使用4. 拷贝构造函数和赋值运算符重载5. empty()6. size()7. insert()(1)pair<iterator,bool> insert(const K& key)(2)iterator insert(iterator pos,cons…...

虚拟DOM是什么

参考文章做的总结&#xff0c;如有不足之处请指正&#xff01; 在讲虚拟dom之前&#xff0c;先讲讲&#xff0c;为什么前端操作dom会导致页面性能降低&#xff1f; 先说几个概念 有助于后面的理解 什么是 JavaScript 引擎&#xff1f; JavaScript引擎是一个专门处理JavaScript脚…...

进程通信方式

无名管道( pipe )&#xff1a; 管道是一种半双工的通信方式&#xff0c;数据只能单向流动&#xff0c;而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。高级管道&#xff08;popen&#xff09;&#xff1a; 将另一个程序当做一个新的进程在当前程序进…...

强化学习基础知识

强化学习是一种机器学习方法&#xff0c;通过agent与environment的互动&#xff0c;学习适当的action policy以取得更大的奖励reward。本篇博客介绍强化学习的基础知识&#xff0c;与两类强化学习模型。 目录强化学习的基础设定policy based 强化学习的目标3个注意事项实际训练…...

LeetCode230218_148、654. 最大二叉树

给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的最大值。 递归地在最大值 左边 的 子数组前缀上 构建左子树。 递归地在最大值 右边 的 子数组后缀上 构建右子树。 返回 nums 构建的 最大二叉树…...

WordPress 是什么?.com 和 .org 的 WordPress 有什么差异?

本篇文章会介绍这次WordPress 5.8核心版本所带来的其中一项新功能&#xff1a;内存块小工具&#xff08;Widget&#xff09;此次更新把小工具编辑设定的页面也改成用「内存块编辑」的概念&#xff0c;就跟内置的「古腾堡」编辑器一样&#xff0c;把所有元件都内存块化&#xff…...

java8新特性【2023】

Lambda表达式 新的一套语法规则 是一个匿名函数 Testpublic void test1(){Runnable r1 new Runnable(){Overridepublic void run() {System.out.println("线程A");}};r1.run();System.out.println("");Runnable r2 () -> System.out.println("…...

刷题记录:牛客NC51101Lost Cows

传送门:牛客 题目描述: (2≤N≤8,000) cows have unique brands in the range 1..N. In a spectacular display of poor judgment, they visited the neighborhood watering hole and drank a few too many beers before dinner. When it was time to line up for their ev…...

华为OD机试 - 不等式 | 备考思路,刷题要点,答疑 【新解法】

最近更新的博客 华为OD机试 - 寻找路径 | 备考思路,刷题要点,答疑 【新解法】华为OD机试 - 最小叶子节点 | 备考思路,刷题要点,答疑 【新解法】华为OD机试 - 对称美学 | 备考思路,刷题要点,答疑 【新解法】华为OD机试 - 最近的点 | 备考思路,刷题要点,答疑 【新解法】华…...

GuLi商城-SpringCloud-OpenFeign测试远程调用

1. Feign 简介 Feign 是一个声明式的 HTTP 客户端&#xff0c;它的目的就是让远程调用更加简单。Feign 提供了HTTP请 求的模板&#xff0c;通过编写简单的接口和插入注解&#xff0c;就可以定义好 HTTP 请求的参数、格式、地址等信 息。Feign 整合了 Ribbon&#xff08;负载…...

阿里云_山东鼎信短信的使用(云市场)

目录山东鼎信API工具类随机验证码工具类进行测试Pom依赖(可以先导入依赖)创建controllerSmsServiceSmsServiceImplswagger测试(也可以使用postman)山东鼎信API工具类 山东鼎信短信官网 找到java的Api&#xff0c;复制下来 适当改了一下&#xff0c;为了调用(类名SmsUtils) p…...

基于虚拟机机的代码保护技术

虚拟机保护技术是基于x86汇编系统的可执行代码转换为字节码指令系统的代码&#xff0c;以达到保护原有指令不被轻易逆向和篡改的目的。 字节码&#xff08;Byte-code&#xff09;是一种包含执行程序&#xff0c;由一序列 op 代码/数据对组成的 &#xff0c;是一种中间码。字节是…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...