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.方式一:继承Thread(2种写法) 写法①(常规): a.使用jconsole观察线程 b.启动线程——start方法 PS:(常见面试题)start 方法与 run 方法的区别: 写…...
驱动调试手段
文章目录 前言一、通过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 第一篇
目录 统一的列表初始化 {}初始化 decltype 编辑 nullptr STL中一些变化 右值引用和移动语义 左值引用和右值引用 总结 左值引用优缺点 右值引用(将亡值) 拷贝赋值和移动赋值 万能引用|完美转发 移动构造和移动赋值注意…...
Spring Data JPA 中 CrudRepository 和 JpaRepository 的区别
1 问题描述Spring Data JPA 中,CrudRepository 和 JpaRepository 有何区别?当我在网上找例子的时候,发现它们可以互相替换使用。它们有什么不同呢?为什么你习惯用其中的一个而不是另一个呢?2 CrudRepository 和 JpaRep…...
推荐几款好用的数据库管理工具
本文主要介绍几款常用的数据库管理软件(客户端),包括开源/免费的、商用收费的,其中有一些是专用于 MySQL 数据库的,例如 MySQL Workbench、phpMyAdmin,有一些是支持多种 SQL、NoSQL 数据库的,例…...
DPDK — 性能优化手段
目录 文章目录 目录硬件布局层面的优化操作系统层面的优化Linux 操作系统版本应用程序层面的优化Cache 优化内存对齐内存预取SIMD 报文批处理DDIO使用高级 CPU 指令集硬件布局层面的优化 DPDK 在硬件布局层面的优化,主要体现在以下几个方面: CPU 频率的高低:CPU 频率越高,…...
Fedora Linux未来五年规划
Fedora 委员会一直致力于起草战略计划,以帮助 Fedora Linux 更好地发展。近日 Fedora 委员会公布了一份 “《未来五年的 Fedora Linux 》” 战略计划草案,这份草案里面包含了他们的雄心壮志:每周将 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是什么
参考文章做的总结,如有不足之处请指正! 在讲虚拟dom之前,先讲讲,为什么前端操作dom会导致页面性能降低? 先说几个概念 有助于后面的理解 什么是 JavaScript 引擎? JavaScript引擎是一个专门处理JavaScript脚…...
进程通信方式
无名管道( pipe ): 管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。高级管道(popen): 将另一个程序当做一个新的进程在当前程序进…...
强化学习基础知识
强化学习是一种机器学习方法,通过agent与environment的互动,学习适当的action policy以取得更大的奖励reward。本篇博客介绍强化学习的基础知识,与两类强化学习模型。 目录强化学习的基础设定policy based 强化学习的目标3个注意事项实际训练…...
LeetCode230218_148、654. 最大二叉树
给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点,其值为 nums 中的最大值。 递归地在最大值 左边 的 子数组前缀上 构建左子树。 递归地在最大值 右边 的 子数组后缀上 构建右子树。 返回 nums 构建的 最大二叉树…...
WordPress 是什么?.com 和 .org 的 WordPress 有什么差异?
本篇文章会介绍这次WordPress 5.8核心版本所带来的其中一项新功能:内存块小工具(Widget)此次更新把小工具编辑设定的页面也改成用「内存块编辑」的概念,就跟内置的「古腾堡」编辑器一样,把所有元件都内存块化ÿ…...
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 客户端,它的目的就是让远程调用更加简单。Feign 提供了HTTP请 求的模板,通过编写简单的接口和插入注解,就可以定义好 HTTP 请求的参数、格式、地址等信 息。Feign 整合了 Ribbon(负载…...
阿里云_山东鼎信短信的使用(云市场)
目录山东鼎信API工具类随机验证码工具类进行测试Pom依赖(可以先导入依赖)创建controllerSmsServiceSmsServiceImplswagger测试(也可以使用postman)山东鼎信API工具类 山东鼎信短信官网 找到java的Api,复制下来 适当改了一下,为了调用(类名SmsUtils) p…...
基于虚拟机机的代码保护技术
虚拟机保护技术是基于x86汇编系统的可执行代码转换为字节码指令系统的代码,以达到保护原有指令不被轻易逆向和篡改的目的。 字节码(Byte-code)是一种包含执行程序,由一序列 op 代码/数据对组成的 ,是一种中间码。字节是…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...







