当前位置: 首页 > 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;是一种中间码。字节是…...

Win10耳机有声音麦不能说话怎么办?麦克风说话别人听不到解决方法

网上找了一些解决办法&#xff0c;一般都是重复的&#xff0c;几个设置调来调去也就那样&#xff0c;没什么用 这种问题一般是“老式”一点的台式机会出现&#xff0c;提供的解决办法如下&#xff1a; 首先下载带面板的音频管理器&#xff0c;如realtek高清晰音频管理器&…...

The 22nd Japanese Olympiad in Informatics (JOI 2022/2023) Final Round 题解

交题&#xff1a;https://cms.ioi-jp.org/documentation A 给一个序列 a1,⋯,ana_1,\cdots,a_na1​,⋯,an​。 执行nnn个操作&#xff0c;第iii个操作为找出第iii个数前离其最近且与它相同的数的位置&#xff0c;把这两个数之间的数全部赋值aia_iai​。求最后的序列。 考虑第…...

openEuler RISC-V 成功适配 VisionFive 2 单板计算机

近日&#xff0c;RISC-V SIG 成功在 VisionFive 2 开发板上适配欧拉操作系统&#xff0c;目前最新版本的 openEuler RISC-V 22.03 V2 镜像已在 VisionFive 2 开发板上可用&#xff0c;这是 openEuler 推动 RISC-V 生态演进的又一新进展。下载链接​​https://mirror.iscas.ac.c…...

2005-2022中国企业对外直接投资、OFDI海外投资明细、中国全球投资追踪数据CGIT(含非建筑施工类问题投资)

中国全球投资跟踪”&#xff08;China Global Investment Tracker&#xff09;&#xff0c;数据库&#xff0c;美国企业研究所于1月28日发布。数据库显示&#xff0c;2005年以来&#xff0c;中国对外投资和建设总额已接近2万亿美元。该数据库是唯一一套涵盖中国全球投资和建设的…...

PCB学习笔记——使用嘉立创在线绘制原理图与PCB

嘉立创软件地址&#xff1a;https://lceda.cn/ 新建工程-新建原理图&#xff0c;在元件库中可以搜索元器件&#xff0c;可以直接放置在原理图上。 原理图绘制完成后&#xff0c;保存文件&#xff0c;设计-原理图转PCB&#xff0c;可以直接生成对应的PCB&#xff0c;设置边框&…...

【C++】类型转化

&#x1f308;欢迎来到C专栏~~类型转化 (꒪ꇴ꒪(꒪ꇴ꒪ )&#x1f423;,我是Scort目前状态&#xff1a;大三非科班啃C中&#x1f30d;博客主页&#xff1a;张小姐的猫~江湖背景快上车&#x1f698;&#xff0c;握好方向盘跟我有一起打天下嘞&#xff01;送给自己的一句鸡汤&…...

Mybatis -- resultMap以及分页

查询为null问题 要解决的问题&#xff1a;属性名和字段名不一致 环境&#xff1a;新建一个项目&#xff0c;将之前的项目拷贝过来 1、查看数据库的字段名 2、Java中的实体类设计 public class User { private int id; //id private String name; //姓名 private String passwo…...

Linux之进程

一.冯诺依曼体系 在计算机中&#xff0c;CPU&#xff08;中央处理器&#xff09;是不直接跟外部设备直接进行通信的&#xff0c;因为CPU处理速度太快了&#xff0c;而设备的数据读取和输入有太慢&#xff0c;而是CPU以及外设直接跟存储器&#xff08;内存&#xff09;打交道&am…...

结构体——“C”

各位CSDN的uu们你们好呀&#xff0c;今天&#xff0c;小雅兰的内容是结构体噢&#xff0c;之前我们在初始C语言中其实就已经学习过了结构体的知识&#xff0c;但是不是很全面&#xff0c;这次&#xff0c;我们也只是稍微详细一点&#xff0c;敬请期待小雅兰之后的博客&#xff…...

CCNP350-401学习笔记(51-100题)

51、Which statement about a fabric access point is true?A. It is in local mode and must be connected directly to the fabric edge switch. B. It is in local mode and must be connected directly to the fabric border node C. It is in FlexConnect mode and must …...

做普通网站公司吗/做一个私人网站需要多少钱

介绍 WebSocket用于在Web浏览器和服务器之间进行任意的双向数据传输的一种技术。WebSocket协议基于TCP协议实现&#xff0c;包含初始的握手过程&#xff0c;以及后续的多次数据帧双向传输过程。其目的是在WebSocket应用和WebSocket服务器进行频繁双向通信时&#xff0c;可以使…...

独立做网站/海外短视频软件

一、IPC (Inter-Process Communication)&#xff1a; --中文翻译是线程间的通信 消息队列共享内存&#xff08;效率最高&#xff09;信号灯集二、客户端命令&#xff1a; ipcs&#xff1a;--用来查看system V的IPC机制标识符的命令-q&#xff0c;显示当前系统中 消息队列 的…...

重庆seo排名方法/青岛招聘seo

ZDNet至顶网服务器频道 05月20日 新闻消息&#xff1a;北京时间5月18日&#xff0c;全新IBM工作室在上海开业&#xff0c;在这里 IBM数字专家和设计精英将与客户共同协作&#xff0c;帮助他们通过大数据、云计算、移动和社交等创新科技更好地与其最终客户进行互动。 IBM工作室座…...

秦淮网站建设/提高百度快速排名

01-求一个整数存储在内存中的二进制中1的个数 法一&#xff1a;循环遍历 问题引入以在十进制中&#xff0c;求某一个数字n中的某个数字m的数量&#xff0c;来引入二进制中求1的个数。 要求一个十进制数n中某一位数字m的个数&#xff0c;只需要让n对10取模与m比较、再让n n /…...

网站互动功能/焊工培训

弹性云服务器 ECS弹性云服务器(Elastic Cloud Server)是一种可随时自助获取、可弹性伸缩的云服务器&#xff0c;帮助用户打造可靠、安全、灵活、高效的应用环境&#xff0c;确保服务持久稳定运行&#xff0c;提升运维效率三年低至5折&#xff0c;多种配置可选了解详情什么是弹性…...

简洁好看的网站/免费推广方法有哪些

在很多情况下&#xff0c;对于监控的安装会有很多人会有疑问。监控作为弱电行业中的一大类&#xff0c;施工人员通常要根据客户的需求进行施工。但对于不同客户的不同需求&#xff0c;要想满足就必须清楚不同的安装方式。今天&#xff0c;就来说说几种网络监控系统安装的几种传…...